Security Vulnerability: Use of insecure eval() in src/djinit/core/parser.py #71

Closed
opened 2026-09-28 02:53:20 +00:00 by mhshibli · 1 comment
mhshibli commented 2026-09-28 02:53:20 +00:00 (Migrated from github.com)

Describe the bug

Hello,

During a static security analysis of the codebase using Bandit, multiple instances of insecure eval() usage were detected in src/djinit/core/parser.py.

Locations:

  • Line 23: return str(eval(key, {"__builtins__": {}}, self.context))
  • Line 47: result = bool(eval(expr, {"__builtins__": {}}, self.context))
  • Line 68: result = bool(eval(expr, {"__builtins__": {}}, self.context))
  • Line 121: iterable = eval(iterable_name, {"__builtins__": {}}, self.context)
  • Line 200: if bool(eval(expr, {"__builtins__": {}}, self.context)):

Impact:
Even though __builtins__ is restricted to an empty dictionary, using eval() on user-supplied or template expressions can lead to Python sandbox escape, potentially allowing arbitrary code execution (Remote Code Execution / Injection vulnerabilities).

Recommendation:
Please consider replacing eval() with a safer alternative like ast.literal_eval() or a dedicated safe template expression parser to avoid security implications.

I would like to request a CVE ID for this finding if verified.

Reproduction

This is a static code analysis vulnerability found in the source code pattern. It can be reproduced by reviewing the eval() statements in src/djinit/core/parser.py. Running any static analysis tool like bandit will trigger this issue immediately.

System Info

- OS: Windows 11
- Python: 3.14.6
- Tool: Bandit 1.9.4 (Static Analysis)

Validations

  • Follow our Code of Conduct
  • Read the Contributing Guide.
  • Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
  • Check that this is a concrete bug. For Q&A, please open a GitHub Discussion instead.
  • The provided reproduction is a minimal reproducible of the bug.
### Describe the bug Hello, During a static security analysis of the codebase using Bandit, multiple instances of insecure `eval()` usage were detected in `src/djinit/core/parser.py`. Locations: - Line 23: `return str(eval(key, {"__builtins__": {}}, self.context))` - Line 47: `result = bool(eval(expr, {"__builtins__": {}}, self.context))` - Line 68: `result = bool(eval(expr, {"__builtins__": {}}, self.context))` - Line 121: `iterable = eval(iterable_name, {"__builtins__": {}}, self.context)` - Line 200: `if bool(eval(expr, {"__builtins__": {}}, self.context)):` Impact: Even though `__builtins__` is restricted to an empty dictionary, using `eval()` on user-supplied or template expressions can lead to Python sandbox escape, potentially allowing arbitrary code execution (Remote Code Execution / Injection vulnerabilities). Recommendation: Please consider replacing `eval()` with a safer alternative like `ast.literal_eval()` or a dedicated safe template expression parser to avoid security implications. I would like to request a CVE ID for this finding if verified. ### Reproduction This is a static code analysis vulnerability found in the source code pattern. It can be reproduced by reviewing the `eval()` statements in `src/djinit/core/parser.py`. Running any static analysis tool like `bandit` will trigger this issue immediately. ### System Info ```Shell - OS: Windows 11 - Python: 3.14.6 - Tool: Bandit 1.9.4 (Static Analysis) ``` ### Validations - [x] Follow our [Code of Conduct](https://github.com/S4NKALP/.github/blob/main/CODE_OF_CONDUCT.md) - [x] Read the [Contributing Guide](https://github.com/S4NKALP/.github/blob/main/CONTRIBUTING.md). - [x] Check that there isn't already an issue that reports the same bug to avoid creating a duplicate. - [x] Check that this is a concrete bug. For Q&A, please open a GitHub Discussion instead. - [x] The provided reproduction is a [minimal reproducible](https://stackoverflow.com/help/minimal-reproducible-example) of the bug.
S4NKALP commented 2026-09-28 08:25:08 +00:00 (Migrated from github.com)

Thanks for the report, and apologies for the trouble.

You are correct. eval(expr, {"__builtins__": {}}, ctx) is not a sandbox. The empty __builtins__ only blocks the obvious name lookups — the object graph reachable from ordinary literals still escapes it, since ().__class__.__base__.__subclasses__() reaches os.system without touching builtins at all. I should not have treated that as containment.

Status: fixed in 0.3.8. All five eval() calls are gone from src/djinit/core/parser.py. Expressions are now evaluated by an explicit AST interpreter with an allow-list, so no code path is reachable. bandit no longer reports the finding. Affected versions: 0.3.4 – 0.3.7. Fixed in 0.3.8.

On the CVE ID: I'm not able to issue one. CVE IDs are assigned by a CNA (e.g. MITRE) at the reporter's request, not by maintainers. If you'd like one, please request it through your CNA, or use GitHub's private vulnerability reporting on the repo. I'm happy to confirm the affected versions and the fix so the advisory is accurate.

Context on severity, so you can triage fairly: djinit renders its own bundled *-tpl files during djinit / djinit setup. Template content is not read from user input at runtime, so exploitation requires a modified or untrusted template inside the installed package rather than a malicious CLI argument. Separately, the old code was already broken for legitimate templates [[ user.name ]] and len(...) silently failed, and dict-attribute loops rendered nothing. The rewrite fixes those too.

Thanks again the report was accurate, and the replacement is better for it.

Thanks for the report, and apologies for the trouble. **You are correct.** `eval(expr, {"__builtins__": {}}, ctx)` is not a sandbox. The empty `__builtins__` only blocks the obvious name lookups — the object graph reachable from ordinary literals still escapes it, since `().__class__.__base__.__subclasses__()` reaches `os.system` without touching builtins at all. I should not have treated that as containment. **Status: fixed in 0.3.8.** All five `eval()` calls are gone from `src/djinit/core/parser.py`. Expressions are now evaluated by an explicit AST interpreter with an allow-list, so no code path is reachable. `bandit` no longer reports the finding. Affected versions: `0.3.4` – `0.3.7`. Fixed in [`0.3.8`](https://github.com/S4NKALP/djinit/releases/tag/0.3.8). **On the CVE ID:** I'm not able to issue one. CVE IDs are assigned by a CNA (e.g. MITRE) at the reporter's request, not by maintainers. If you'd like one, please request it through your CNA, or use GitHub's private vulnerability reporting on the repo. I'm happy to confirm the affected versions and the fix so the advisory is accurate. **Context on severity, so you can triage fairly:** djinit renders its own bundled `*-tpl` files during `djinit` / `djinit setup`. Template content is not read from user input at runtime, so exploitation requires a modified or untrusted template inside the installed package rather than a malicious CLI argument. Separately, the old code was already broken for legitimate templates `[[ user.name ]]` and `len(...)` silently failed, and dict-attribute loops rendered nothing. The rewrite fixes those too. Thanks again the report was accurate, and the replacement is better for it.
Sign in to join this conversation.