Skip to content

feat(skills): harden the file upload validation section in django-security#2338

Open
jvirgovic wants to merge 4 commits into
affaan-m:mainfrom
jvirgovic:update-django-security-file-upload-validation
Open

feat(skills): harden the file upload validation section in django-security#2338
jvirgovic wants to merge 4 commits into
affaan-m:mainfrom
jvirgovic:update-django-security-file-upload-validation

Conversation

@jvirgovic

Copy link
Copy Markdown

What Changed

Replaced the insecure extension-only file validation in the Django Security skill with magic byte validation using python-magic (with a pure-Python filetype alternative). The validator now reads file signatures to determine actual MIME type and cross-checks against the declared extension.

Why This Change

Extension-based file validation is trivially bypassed by renaming files. Magic byte inspection verifies the actual file content, providing meaningful upload security rather than a false sense of safety.

Testing Done

  • Manual testing completed
  • Automated tests pass locally (node tests/run-all.js)
  • Edge cases considered and tested

Type of Change

  • fix: Bug fix
  • feat: New feature
  • refactor: Code refactoring
  • docs: Documentation
  • test: Tests
  • chore: Maintenance/tooling
  • ci: CI/CD changes

Security & Quality Checklist

  • No secrets or API keys committed (ghp_, sk-, AKIA, xoxb, xoxp patterns checked)
  • JSON files validate cleanly
  • Shell scripts pass shellcheck (if applicable)
  • Pre-commit hooks pass locally (if configured)
  • No sensitive data exposed in logs or output
  • Follows conventional commits format

Documentation

  • Updated relevant documentation
  • Added comments for complex logic
  • README updated (if needed)

@jvirgovic jvirgovic requested a review from affaan-m as a code owner June 22, 2026 18:46
@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • Documentation
    • Updated file upload security guidance to validate uploaded files using content-based MIME/type detection instead of relying on file extensions alone.
    • Added guidance for both native and pure-Python MIME detection environments, including checks that the detected MIME aligns with the uploaded file’s extension.
    • Ensured file size validation continues to apply alongside the new type checks.

Walkthrough

The File Upload Security section in skills/django-security/SKILL.md replaces extension-only validation with MIME/magic-bytes detection using python-magic. It adds ALLOWED_MIMES, MIME_TO_EXTENSIONS, and a new validate_file_type validator, updates Document.file validators, and adds a filetype-package fallback for environments without libmagic.

Changes

File Upload Security Guidance Update

Layer / File(s) Summary
MIME sniffing validators with python-magic and filetype fallback
skills/django-security/SKILL.md
Removes validate_file_extension; adds ALLOWED_MIMES allowlist, MIME_TO_EXTENSIONS map, and validate_file_type using python-magic to sniff MIME from uploaded bytes and cross-check extension consistency. Document.file validators updated to [validate_file_type, validate_file_size]. A second validate_file_type variant using the pure-Python filetype package is added as a libmagic-free fallback.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

Two validators walked in, one walked out 🧙
Extension checks banished, magic bytes devout
MIME sniffing now guards what uploads may bring
With filetype as backup—a fallback safety ring
No spoofed .pdf shall pass this gatekeeper's sting 🔒

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately reflects the main change: hardening file upload validation in the Django Security skill by replacing extension-only checks with magic byte validation.
Description check ✅ Passed The description is directly related to the changeset, explaining the shift from extension-based to magic byte validation and the security rationale behind it.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps

greptile-apps Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR hardens the file upload validation section of the Django Security skill by replacing the old extension-only validator with magic-byte inspection, providing both a python-magic (primary) and a pure-Python filetype (alternative) implementation.

  • The new validate_file_type validator reads the first 2048 bytes to determine the actual MIME type via magic bytes, then cross-checks the declared file extension against an allow-list — correctly calling value.seek(0) after the read so downstream validators receive a fully rewound file.
  • Both code blocks are now self-contained with all required imports, constants (ALLOWED_MIMES, MIME_TO_EXTENSIONS), and error messages, and the filetype block is appropriately scoped to the "minimal container" use case where installing libmagic is impractical.

Confidence Score: 5/5

Documentation-only change to a skill guide; no runtime code is modified and both validator snippets are logically correct and self-contained.

The magic-byte validation logic is sound — file pointer is rewound after the read, the allow-list check happens before the extension cross-check, and the filetype alternative handles the None return correctly. Both snippets are now complete and self-contained. The only gaps are minor documentation nits.

No files require special attention.

Important Files Changed

Filename Overview
skills/django-security/SKILL.md Replaces extension-only file validation with magic-byte inspection via python-magic (primary) and filetype (pure-Python alternative). Both blocks are now self-contained with all required imports and constants. Minor documentation gaps: missing system-library install hint for python-magic, and an incomplete docstring in the filetype variant.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[File Upload] --> B[validate_file_type]
    B --> C["Read first 2048 bytes\n(value.read(2048))"]
    C --> D{libmagic available?}
    D -- Yes --> E["magic.from_buffer()\nreturns MIME string"]
    D -- No --> F["filetype.guess()\nreturns kind or None"]
    E --> G{MIME in ALLOWED_MIMES?}
    F --> G
    G -- No --> H[ValidationError:\nUnsupported file type]
    G -- Yes --> I["value.seek(0)\nReset file pointer"]
    I --> J["Check extension vs\nMIME_TO_EXTENSIONS"]
    J -- Mismatch --> K[ValidationError:\nExtension mismatch]
    J -- Match --> L[validate_file_size]
    L --> M{size > 5 MB?}
    M -- Yes --> N[ValidationError:\nFile too large]
    M -- No --> O[Validation passes\nFile saved]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[File Upload] --> B[validate_file_type]
    B --> C["Read first 2048 bytes\n(value.read(2048))"]
    C --> D{libmagic available?}
    D -- Yes --> E["magic.from_buffer()\nreturns MIME string"]
    D -- No --> F["filetype.guess()\nreturns kind or None"]
    E --> G{MIME in ALLOWED_MIMES?}
    F --> G
    G -- No --> H[ValidationError:\nUnsupported file type]
    G -- Yes --> I["value.seek(0)\nReset file pointer"]
    I --> J["Check extension vs\nMIME_TO_EXTENSIONS"]
    J -- Mismatch --> K[ValidationError:\nExtension mismatch]
    J -- Match --> L[validate_file_size]
    L --> M{size > 5 MB?}
    M -- Yes --> N[ValidationError:\nFile too large]
    M -- No --> O[Validation passes\nFile saved]
Loading

Reviews (3): Last reviewed commit: "add import to the top of the code block" | Re-trigger Greptile

Comment thread skills/django-security/SKILL.md
Comment thread skills/django-security/SKILL.md Outdated

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@skills/django-security/SKILL.md`:
- Around line 409-419: The validate_file_type function reads magic bytes from
the current cursor position and only resets afterward, which fails if the file
has already been read elsewhere. Capture the original file position using tell()
at the start of the function, seek to position 0 before reading the buffer for
mime type detection, and restore the original file offset after validation using
a finally block to ensure the position is always restored regardless of whether
validation succeeds or raises an error.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 73f9ced7-27ad-452e-8d6c-cb7a1a1e2e68

📥 Commits

Reviewing files that changed from the base of the PR and between 71d22d0 and 731fb14.

📒 Files selected for processing (1)
  • skills/django-security/SKILL.md
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: Greptile Review
🧰 Additional context used
📓 Path-based instructions (3)
skills/**/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

Skills should be formatted as Markdown with clear sections for When to Use, How It Works, and Examples.

Files:

  • skills/django-security/SKILL.md
{agents,skills,commands}/**/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

Use lowercase filenames with hyphens (e.g., python-reviewer.md, tdd-workflow.md) for agents, skills, and commands.

Files:

  • skills/django-security/SKILL.md
{skills,commands,agents,rules}/**

⚙️ CodeRabbit configuration file

{skills,commands,agents,rules}/**: Focus on prompt-injection resilience, tool-permission scope, destructive action guards, and secret exfiltration risks.

Files:

  • skills/django-security/SKILL.md
🧠 Learnings (2)
📚 Learning: 2026-03-15T19:02:43.245Z
Learnt from: imrobinsingh
Repo: affaan-m/everything-claude-code PR: 503
File: skills/data-scraper-agent/SKILL.md:1-748
Timestamp: 2026-03-15T19:02:43.245Z
Learning: In this repository, skill folders should use a lowercase-hyphen name (e.g., data-scraper-agent, claude-api) and the skill description file inside each folder should be named SKILL.md (uppercase). Do not flag SKILL.md as a naming violation; treat SKILL.md as the canonical file name inside each skill directory.

Applied to files:

  • skills/django-security/SKILL.md
📚 Learning: 2026-04-15T15:52:59.963Z
Learnt from: manja316
Repo: affaan-m/everything-claude-code PR: 1360
File: skills/security-bounty-hunter/SKILL.md:11-18
Timestamp: 2026-04-15T15:52:59.963Z
Learning: In this repository’s skills documentation (skills/**/SKILL.md), use the canonical auto-activation skill section header `## When to Activate`—do not use `## When to Use`. CONTRIBUTING.md and docs/SKILL-DEVELOPMENT-GUIDE.md confirm the required header, and existing skills follow this convention. This header is important for the auto-activation mechanism to detect the correct section.

Applied to files:

  • skills/django-security/SKILL.md
🪛 SkillSpector (2.2.3)
skills/django-security/SKILL.md

[error] 50: [E2] Env Variable Harvesting: Code accesses environment variables that may contain secrets (API keys, tokens). This is a common pattern for credential theft.

Remediation: Avoid reading sensitive env vars (API keys, tokens) unless strictly required. Use secrets managers or secure config. Never log or transmit credentials.

(Data Exfiltration (E2))


[error] 566: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))


[error] 573: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))

Comment on lines +409 to +419
def validate_file_type(value):
"""Validate file type using magic bytes and cross-check extension."""
mime = magic.from_buffer(value.read(2048), mime=True)
value.seek(0)

if mime not in ALLOWED_MIMES:
raise ValidationError(f'Unsupported file type: {mime}')

ext = os.path.splitext(value.name)[1].lower()
if ext not in MIME_TO_EXTENSIONS.get(mime, set()):
raise ValidationError('File extension does not match file content.')

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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Read from the start, then restore the original file position.

Both validator variants sniff from the current cursor position and only rewind afterward. If anything has already read the upload, this validates the wrong bytes and can reject a valid file. Capture tell(), seek to 0 before sniffing, and restore the original offset in a finally block.

✅ Proposed fix
 def validate_file_type(value):
     """Validate file type using magic bytes and cross-check extension."""
-    mime = magic.from_buffer(value.read(2048), mime=True)
-    value.seek(0)
+    pos = value.tell()
+    try:
+        value.seek(0)
+        mime = magic.from_buffer(value.read(2048), mime=True)
+    finally:
+        value.seek(pos)

Also applies to: 441-451

🧰 Tools
🪛 SkillSpector (2.2.3)

[error] 50: [E2] Env Variable Harvesting: Code accesses environment variables that may contain secrets (API keys, tokens). This is a common pattern for credential theft.

Remediation: Avoid reading sensitive env vars (API keys, tokens) unless strictly required. Use secrets managers or secure config. Never log or transmit credentials.

(Data Exfiltration (E2))


[error] 566: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))


[error] 573: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/django-security/SKILL.md` around lines 409 - 419, The
validate_file_type function reads magic bytes from the current cursor position
and only resets afterward, which fails if the file has already been read
elsewhere. Capture the original file position using tell() at the start of the
function, seek to position 0 before reading the buffer for mime type detection,
and restore the original file offset after validation using a finally block to
ensure the position is always restored regardless of whether validation succeeds
or raises an error.

jvirgovic and others added 3 commits June 22, 2026 18:56
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

@coderabbitai coderabbitai Bot left a comment

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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
skills/django-security/SKILL.md (2)

409-420: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

File position must be captured, preserved, and restored in a finally block.

The validator reads magic bytes from the current cursor position (line 411) and only seeks back to 0 afterward (line 412). If the file has been read elsewhere in the upload pipeline, the cursor will not be at position 0, and this code will sniff the wrong bytes. This can cause valid files to be rejected or (worse) bypass validation.

Capture the original position using tell(), seek to 0 before sniffing, and unconditionally restore the original position in a finally block.

🔧 Proposed fix
 def validate_file_type(value):
     """Validate file type using magic bytes and cross-check extension."""
-    mime = magic.from_buffer(value.read(2048), mime=True)
-    value.seek(0)
+    pos = value.tell()
+    try:
+        value.seek(0)
+        mime = magic.from_buffer(value.read(2048), mime=True)
+    finally:
+        value.seek(pos)
 
     if mime not in ALLOWED_MIMES:
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/django-security/SKILL.md` around lines 409 - 420, The
validate_file_type function must preserve the original file cursor position
since it may not be at position 0 when called. Capture the original position at
the start of the function using the tell() method, then seek to position 0
before reading the magic bytes. Wrap the validation logic in a try-finally block
that unconditionally restores the original position in the finally clause,
ensuring the cursor is restored even if an exception occurs during validation.

393-407: ⚠️ Potential issue | 🟡 Minor

Add "When to Activate" subsection to File Upload Security section.

The File Upload Security section (line 389) lacks a ### When to Activate subsection, jumping directly to ### File Validation. Add a brief subsection describing when file upload validation should be applied to align with the skill's auto-activation mechanism documented at line 12.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/django-security/SKILL.md` around lines 393 - 407, The File Upload
Security section is missing a "When to Activate" subsection that should appear
before the "File Validation" subsection. Add a "### When to Activate" heading
after the main section header for File Upload Security and include a brief
description of when file upload validation should be applied to the application.
Reference and align this activation guidance with the skill's auto-activation
mechanism documented earlier in the document (at line 12) to maintain
consistency with the document structure.

Source: Learnings

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@skills/django-security/SKILL.md`:
- Around line 409-420: The validate_file_type function must preserve the
original file cursor position since it may not be at position 0 when called.
Capture the original position at the start of the function using the tell()
method, then seek to position 0 before reading the magic bytes. Wrap the
validation logic in a try-finally block that unconditionally restores the
original position in the finally clause, ensuring the cursor is restored even if
an exception occurs during validation.
- Around line 393-407: The File Upload Security section is missing a "When to
Activate" subsection that should appear before the "File Validation" subsection.
Add a "### When to Activate" heading after the main section header for File
Upload Security and include a brief description of when file upload validation
should be applied to the application. Reference and align this activation
guidance with the skill's auto-activation mechanism documented earlier in the
document (at line 12) to maintain consistency with the document structure.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: e788b6ae-41e4-4573-bdcf-a404be9fb6dc

📥 Commits

Reviewing files that changed from the base of the PR and between 731fb14 and add54bb.

📒 Files selected for processing (1)
  • skills/django-security/SKILL.md
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: Greptile Review
🧰 Additional context used
📓 Path-based instructions (3)
skills/**/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

Skills should be formatted as Markdown with clear sections for When to Use, How It Works, and Examples.

Files:

  • skills/django-security/SKILL.md
{agents,skills,commands}/**/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

Use lowercase filenames with hyphens (e.g., python-reviewer.md, tdd-workflow.md) for agents, skills, and commands.

Files:

  • skills/django-security/SKILL.md
{skills,commands,agents,rules}/**

⚙️ CodeRabbit configuration file

{skills,commands,agents,rules}/**: Focus on prompt-injection resilience, tool-permission scope, destructive action guards, and secret exfiltration risks.

Files:

  • skills/django-security/SKILL.md
🧠 Learnings (2)
📚 Learning: 2026-03-15T19:02:43.245Z
Learnt from: imrobinsingh
Repo: affaan-m/everything-claude-code PR: 503
File: skills/data-scraper-agent/SKILL.md:1-748
Timestamp: 2026-03-15T19:02:43.245Z
Learning: In this repository, skill folders should use a lowercase-hyphen name (e.g., data-scraper-agent, claude-api) and the skill description file inside each folder should be named SKILL.md (uppercase). Do not flag SKILL.md as a naming violation; treat SKILL.md as the canonical file name inside each skill directory.

Applied to files:

  • skills/django-security/SKILL.md
📚 Learning: 2026-04-15T15:52:59.963Z
Learnt from: manja316
Repo: affaan-m/everything-claude-code PR: 1360
File: skills/security-bounty-hunter/SKILL.md:11-18
Timestamp: 2026-04-15T15:52:59.963Z
Learning: In this repository’s skills documentation (skills/**/SKILL.md), use the canonical auto-activation skill section header `## When to Activate`—do not use `## When to Use`. CONTRIBUTING.md and docs/SKILL-DEVELOPMENT-GUIDE.md confirm the required header, and existing skills follow this convention. This header is important for the auto-activation mechanism to detect the correct section.

Applied to files:

  • skills/django-security/SKILL.md
🪛 SkillSpector (2.2.3)
skills/django-security/SKILL.md

[error] 50: [E2] Env Variable Harvesting: Code accesses environment variables that may contain secrets (API keys, tokens). This is a common pattern for credential theft.

Remediation: Avoid reading sensitive env vars (API keys, tokens) unless strictly required. Use secrets managers or secure config. Never log or transmit credentials.

(Data Exfiltration (E2))


[error] 566: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))


[error] 573: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))

🔇 Additional comments (1)
skills/django-security/SKILL.md (1)

435-451: The fallback implementation is consistent but lacks proper runtime gating.

Both validate_file_type functions apply identical validation logic:

  • File position preservation (read + seek)
  • ALLOWED_MIMES enforcement
  • Extension verification against MIME_TO_EXTENSIONS

However, the code shows these as separate documentation examples rather than a runtime fallback pattern. There's no try-import or except block that would automatically fall back from magic to filetype on ImportError. Developers must manually choose which implementation to use; they won't get automatic fallback behavior. Either wire a try-except pattern around the imports or clarify that this is a manual swap, not an automatic failover.

@coderabbitai coderabbitai Bot left a comment

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.

♻️ Duplicate comments (1)
skills/django-security/SKILL.md (1)

409-419: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Preserve the original file cursor before sniffing.

Both snippets still read from the current position and only rewind afterward, so any prior read can make validation inspect the wrong bytes and reject a valid upload. Capture tell(), seek to 0 before sniffing, and restore the original offset in finally.

🔧 Proposed fix
 def validate_file_type(value):
     """Validate file type using magic bytes and cross-check extension."""
-    mime = magic.from_buffer(value.read(2048), mime=True)
-    value.seek(0)
+    pos = value.tell()
+    try:
+        value.seek(0)
+        mime = magic.from_buffer(value.read(2048), mime=True)
+    finally:
+        value.seek(pos)

Also applies to: 455-465

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/django-security/SKILL.md` around lines 409 - 419, The
validate_file_type function reads from the current file position and only
rewinds to position 0 afterward, which fails to preserve the original cursor
position if the file was already read. Capture the current position using
value.tell() before reading, seek to position 0 before performing the magic
bytes check, and use a finally block to restore the original cursor position
after the validation completes to ensure subsequent operations access the file
from the correct offset.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@skills/django-security/SKILL.md`:
- Around line 409-419: The validate_file_type function reads from the current
file position and only rewinds to position 0 afterward, which fails to preserve
the original cursor position if the file was already read. Capture the current
position using value.tell() before reading, seek to position 0 before performing
the magic bytes check, and use a finally block to restore the original cursor
position after the validation completes to ensure subsequent operations access
the file from the correct offset.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5415e11e-de23-4cb8-bc1b-7b689db4055c

📥 Commits

Reviewing files that changed from the base of the PR and between add54bb and 13f70cc.

📒 Files selected for processing (1)
  • skills/django-security/SKILL.md
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: Greptile Review
🧰 Additional context used
📓 Path-based instructions (3)
skills/**/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

Skills should be formatted as Markdown with clear sections for When to Use, How It Works, and Examples.

Files:

  • skills/django-security/SKILL.md
{agents,skills,commands}/**/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

Use lowercase filenames with hyphens (e.g., python-reviewer.md, tdd-workflow.md) for agents, skills, and commands.

Files:

  • skills/django-security/SKILL.md
{skills,commands,agents,rules}/**

⚙️ CodeRabbit configuration file

{skills,commands,agents,rules}/**: Focus on prompt-injection resilience, tool-permission scope, destructive action guards, and secret exfiltration risks.

Files:

  • skills/django-security/SKILL.md
🧠 Learnings (2)
📚 Learning: 2026-03-15T19:02:43.245Z
Learnt from: imrobinsingh
Repo: affaan-m/everything-claude-code PR: 503
File: skills/data-scraper-agent/SKILL.md:1-748
Timestamp: 2026-03-15T19:02:43.245Z
Learning: In this repository, skill folders should use a lowercase-hyphen name (e.g., data-scraper-agent, claude-api) and the skill description file inside each folder should be named SKILL.md (uppercase). Do not flag SKILL.md as a naming violation; treat SKILL.md as the canonical file name inside each skill directory.

Applied to files:

  • skills/django-security/SKILL.md
📚 Learning: 2026-04-15T15:52:59.963Z
Learnt from: manja316
Repo: affaan-m/everything-claude-code PR: 1360
File: skills/security-bounty-hunter/SKILL.md:11-18
Timestamp: 2026-04-15T15:52:59.963Z
Learning: In this repository’s skills documentation (skills/**/SKILL.md), use the canonical auto-activation skill section header `## When to Activate`—do not use `## When to Use`. CONTRIBUTING.md and docs/SKILL-DEVELOPMENT-GUIDE.md confirm the required header, and existing skills follow this convention. This header is important for the auto-activation mechanism to detect the correct section.

Applied to files:

  • skills/django-security/SKILL.md
🪛 SkillSpector (2.2.3)
skills/django-security/SKILL.md

[error] 50: [E2] Env Variable Harvesting: Code accesses environment variables that may contain secrets (API keys, tokens). This is a common pattern for credential theft.

Remediation: Avoid reading sensitive env vars (API keys, tokens) unless strictly required. Use secrets managers or secure config. Never log or transmit credentials.

(Data Exfiltration (E2))


[error] 580: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))


[error] 587: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))

@daltino daltino left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This PR strengthens the file upload validation logic in django-security by moving from validating file extensions to MIME type validation using the python-magic library. This is a robust improvement since MIME types are harder to spoof than file extensions. The ALLOWED_MIMES and MIME_TO_EXTENSIONS mappings are a good addition for better control and clarity. The changes themselves are concise and align well with the goal of enhancing security.

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.

2 participants