Skip to content

security: replace unsafe eval() with ast.literal_eval()#7379

Open
thesohamdatta wants to merge 2 commits into
BasedHardware:mainfrom
thesohamdatta:fix/security-eval-injection
Open

security: replace unsafe eval() with ast.literal_eval()#7379
thesohamdatta wants to merge 2 commits into
BasedHardware:mainfrom
thesohamdatta:fix/security-eval-injection

Conversation

@thesohamdatta
Copy link
Copy Markdown

replaces unsafe eval() with ast.literal_eval() to prevent rce in redis handlers. minimal fix following repo standards

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 19, 2026

Greptile Summary

This PR replaces bare eval() calls with ast.literal_eval() across backend/database/redis_db.py and plugins/db.py to prevent remote code execution when deserializing Redis-stored data. The intent is correct, but both files are missing import ast, which means every modified function will throw NameError: name 'ast' is not defined in production.

  • backend/database/redis_db.py: 7 eval() calls replaced across usage-count, money, reviews, and geolocation cache helpers — all broken at runtime without import ast.
  • plugins/db.py: 2 eval() calls replaced in transcript-segment append/upsert helpers — same missing import issue.

Confidence Score: 1/5

Not safe to merge — every function touched by this PR will crash at runtime due to a missing import.

The fix correctly swaps eval() for ast.literal_eval(), but neither changed file imports the ast module. Every Redis read path that was modified — including app reviews, usage counts, geolocation cache, and transcript segments — will throw NameError: name 'ast' is not defined on the first call. The try_catch_decorator wrapping most of these functions will silently swallow the error and return None, so callers will get empty or null data rather than an explicit failure, making this regression easy to miss without careful testing.

Both backend/database/redis_db.py and plugins/db.py need import ast added to their top-level imports before this can be merged.

Important Files Changed

Filename Overview
backend/database/redis_db.py Replaces 7 bare eval() calls with ast.literal_eval(), but omits the required import ast — all changed functions will raise NameError at runtime.
plugins/db.py Replaces 2 bare eval() calls with ast.literal_eval(), but omits the required import ast — both transcript-segment functions will raise NameError at runtime.

Reviews (1): Last reviewed commit: "security: replace unsafe eval() with ast..." | Re-trigger Greptile

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: be34b72c2c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread backend/database/redis_db.py Outdated
if not count:
return None
return eval(count)
return ast.literal_eval(count)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Decode Redis bytes before literal_eval

This Redis client is constructed without decode_responses=True, so r.get(...) returns bytes; eval accepted byte strings, but ast.literal_eval(b'123') raises ValueError. On any existing cache hit for usage counts/money/reviews, these getters now fail instead of returning the cached value, so decode the Redis value before passing it to literal_eval.

Useful? React with 👍 / 👎.

Comment thread plugins/db.py Outdated
segments = []
else:
segments = eval(segments)
segments = ast.literal_eval(segments)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Decode transcript cache values before literal_eval

The Redis client here also returns bytes, and ast.literal_eval does not accept byte strings even though the previous eval did. When a transcript key already exists, append_segment_to_transcript and the plugin transcript upsert path will raise instead of appending segments, so the value needs decoding before literal_eval.

Useful? React with 👍 / 👎.

Comment thread backend/database/redis_db.py Outdated
if not count:
return None
return eval(count)
return ast.literal_eval(count)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P0 Missing import ast — all changed functions will raise NameError at runtime

ast is never imported in this file, so every call to ast.literal_eval() introduced by this PR will immediately throw NameError: name 'ast' is not defined. That means get_app_usage_count_cache, get_app_money_made_amount_cache, set_app_review_cache, get_specific_user_review, get_app_reviews, get_apps_reviews, and get_cached_user_geolocation are all broken. Add import ast to the top-level imports (alongside import json, import os, etc.).

Suggested change
return ast.literal_eval(count)
import ast
import base64
import json
import os
from typing import List, Union, Optional
from datetime import datetime, timedelta, timezone
import redis
import logging

Comment thread plugins/db.py Outdated
@thesohamdatta
Copy link
Copy Markdown
Author

I've pushed an update that fully addresses the Greptile and Codex feedback.

beyond fixing the missing ast imports and decoding the Redis bytes, I also audited the migration scripts and replaced some unsafe eval() calls there with
json.loads(). The fix has been verified with a local test suite to ensure stability across Python versions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant