safeuploads 1.1.1__tar.gz → 1.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. {safeuploads-1.1.1 → safeuploads-1.1.2}/.github/workflows/audit-safeuploads.yml +1 -1
  2. {safeuploads-1.1.1 → safeuploads-1.1.2}/.github/workflows/conventional-commits.yml +7 -2
  3. {safeuploads-1.1.1 → safeuploads-1.1.2}/.github/workflows/docs.yml +2 -2
  4. {safeuploads-1.1.1 → safeuploads-1.1.2}/.github/workflows/fuzz.yml +1 -1
  5. {safeuploads-1.1.1 → safeuploads-1.1.2}/.github/workflows/lint-and-test.yml +3 -3
  6. {safeuploads-1.1.1 → safeuploads-1.1.2}/.github/workflows/publish-safeuploads.yml +7 -7
  7. safeuploads-1.1.2/.github/workflows/test-matrix-safeuploads.yml +104 -0
  8. safeuploads-1.1.2/CHANGELOG.md +114 -0
  9. {safeuploads-1.1.1 → safeuploads-1.1.2}/PKG-INFO +2 -2
  10. {safeuploads-1.1.1 → safeuploads-1.1.2}/pyproject.toml +2 -2
  11. safeuploads-1.1.2/uv.lock +1308 -0
  12. safeuploads-1.1.1/CHANGELOG.md +0 -161
  13. safeuploads-1.1.1/uv.lock +0 -1120
  14. {safeuploads-1.1.1 → safeuploads-1.1.2}/.github/CODEOWNERS +0 -0
  15. {safeuploads-1.1.1 → safeuploads-1.1.2}/.github/FUNDING.yml +0 -0
  16. {safeuploads-1.1.1 → safeuploads-1.1.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  17. {safeuploads-1.1.1 → safeuploads-1.1.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  18. {safeuploads-1.1.1 → safeuploads-1.1.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  19. {safeuploads-1.1.1 → safeuploads-1.1.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  20. {safeuploads-1.1.1 → safeuploads-1.1.2}/.github/agents/se-gitops-ci-specialist.agent.md +0 -0
  21. {safeuploads-1.1.1 → safeuploads-1.1.2}/.github/agents/se-security-reviewer.agent.md +0 -0
  22. {safeuploads-1.1.1 → safeuploads-1.1.2}/.github/agents/test-implementor.agent.md +0 -0
  23. {safeuploads-1.1.1 → safeuploads-1.1.2}/.github/agents/test-reviewer.agent.md +0 -0
  24. {safeuploads-1.1.1 → safeuploads-1.1.2}/.github/copilot-instructions.md +0 -0
  25. {safeuploads-1.1.1 → safeuploads-1.1.2}/.github/dependabot.yml +0 -0
  26. {safeuploads-1.1.1 → safeuploads-1.1.2}/.github/instructions/agents.instructions.md +0 -0
  27. {safeuploads-1.1.1 → safeuploads-1.1.2}/.github/instructions/github-actions-ci-cd-best-practices.instructions.md +0 -0
  28. {safeuploads-1.1.1 → safeuploads-1.1.2}/.github/instructions/instructions.instructions.md +0 -0
  29. {safeuploads-1.1.1 → safeuploads-1.1.2}/.github/instructions/prompt.instructions.md +0 -0
  30. {safeuploads-1.1.1 → safeuploads-1.1.2}/.github/instructions/python.instructions.md +0 -0
  31. {safeuploads-1.1.1 → safeuploads-1.1.2}/.github/instructions/security-and-owasp.instructions.md +0 -0
  32. {safeuploads-1.1.1 → safeuploads-1.1.2}/.github/scripts/check_conventional_commits.py +0 -0
  33. {safeuploads-1.1.1 → safeuploads-1.1.2}/.github/scripts/smoke_import.py +0 -0
  34. {safeuploads-1.1.1 → safeuploads-1.1.2}/.github/workflows/mirror.yml +0 -0
  35. {safeuploads-1.1.1 → safeuploads-1.1.2}/.gitignore +0 -0
  36. {safeuploads-1.1.1 → safeuploads-1.1.2}/CODE_OF_CONDUCT.md +0 -0
  37. {safeuploads-1.1.1 → safeuploads-1.1.2}/CONTRIBUTING.md +0 -0
  38. {safeuploads-1.1.1 → safeuploads-1.1.2}/LICENSE.md +0 -0
  39. {safeuploads-1.1.1 → safeuploads-1.1.2}/README.md +0 -0
  40. {safeuploads-1.1.1 → safeuploads-1.1.2}/SECURITY.md +0 -0
  41. {safeuploads-1.1.1 → safeuploads-1.1.2}/docs/api.md +0 -0
  42. {safeuploads-1.1.1 → safeuploads-1.1.2}/docs/index.md +0 -0
  43. {safeuploads-1.1.1 → safeuploads-1.1.2}/docs/rate-limiting.md +0 -0
  44. {safeuploads-1.1.1 → safeuploads-1.1.2}/docs/security/architecture.md +0 -0
  45. {safeuploads-1.1.1 → safeuploads-1.1.2}/docs/security/integration-checklist.md +0 -0
  46. {safeuploads-1.1.1 → safeuploads-1.1.2}/docs/security/threat-model.md +0 -0
  47. {safeuploads-1.1.1 → safeuploads-1.1.2}/examples/README.md +0 -0
  48. {safeuploads-1.1.1 → safeuploads-1.1.2}/examples/fastapi_example.py +0 -0
  49. {safeuploads-1.1.1 → safeuploads-1.1.2}/mkdocs.yml +0 -0
  50. {safeuploads-1.1.1 → safeuploads-1.1.2}/safeuploads/__init__.py +0 -0
  51. {safeuploads-1.1.1 → safeuploads-1.1.2}/safeuploads/audit.py +0 -0
  52. {safeuploads-1.1.1 → safeuploads-1.1.2}/safeuploads/config.py +0 -0
  53. {safeuploads-1.1.1 → safeuploads-1.1.2}/safeuploads/enums.py +0 -0
  54. {safeuploads-1.1.1 → safeuploads-1.1.2}/safeuploads/exceptions.py +0 -0
  55. {safeuploads-1.1.1 → safeuploads-1.1.2}/safeuploads/file_validator.py +0 -0
  56. {safeuploads-1.1.1 → safeuploads-1.1.2}/safeuploads/inspectors/__init__.py +0 -0
  57. {safeuploads-1.1.1 → safeuploads-1.1.2}/safeuploads/inspectors/base.py +0 -0
  58. {safeuploads-1.1.1 → safeuploads-1.1.2}/safeuploads/inspectors/content_inspector.py +0 -0
  59. {safeuploads-1.1.1 → safeuploads-1.1.2}/safeuploads/inspectors/gzip_inspector.py +0 -0
  60. {safeuploads-1.1.1 → safeuploads-1.1.2}/safeuploads/inspectors/zip_inspector.py +0 -0
  61. {safeuploads-1.1.1 → safeuploads-1.1.2}/safeuploads/protocols.py +0 -0
  62. {safeuploads-1.1.1 → safeuploads-1.1.2}/safeuploads/py.typed +0 -0
  63. {safeuploads-1.1.1 → safeuploads-1.1.2}/safeuploads/utils.py +0 -0
  64. {safeuploads-1.1.1 → safeuploads-1.1.2}/safeuploads/validators/__init__.py +0 -0
  65. {safeuploads-1.1.1 → safeuploads-1.1.2}/safeuploads/validators/base.py +0 -0
  66. {safeuploads-1.1.1 → safeuploads-1.1.2}/safeuploads/validators/compression_validator.py +0 -0
  67. {safeuploads-1.1.1 → safeuploads-1.1.2}/safeuploads/validators/extension_validator.py +0 -0
  68. {safeuploads-1.1.1 → safeuploads-1.1.2}/safeuploads/validators/unicode_validator.py +0 -0
  69. {safeuploads-1.1.1 → safeuploads-1.1.2}/safeuploads/validators/windows_validator.py +0 -0
  70. {safeuploads-1.1.1 → safeuploads-1.1.2}/safeuploads/validators/xml_validator.py +0 -0
  71. {safeuploads-1.1.1 → safeuploads-1.1.2}/tests/__init__.py +0 -0
  72. {safeuploads-1.1.1 → safeuploads-1.1.2}/tests/conftest.py +0 -0
  73. {safeuploads-1.1.1 → safeuploads-1.1.2}/tests/fuzz/__init__.py +0 -0
  74. {safeuploads-1.1.1 → safeuploads-1.1.2}/tests/fuzz/test_fuzz_config.py +0 -0
  75. {safeuploads-1.1.1 → safeuploads-1.1.2}/tests/fuzz/test_fuzz_filenames.py +0 -0
  76. {safeuploads-1.1.1 → safeuploads-1.1.2}/tests/fuzz/test_fuzz_images.py +0 -0
  77. {safeuploads-1.1.1 → safeuploads-1.1.2}/tests/fuzz/test_fuzz_zip.py +0 -0
  78. {safeuploads-1.1.1 → safeuploads-1.1.2}/tests/inspectors/__init__.py +0 -0
  79. {safeuploads-1.1.1 → safeuploads-1.1.2}/tests/inspectors/test_content_inspector.py +0 -0
  80. {safeuploads-1.1.1 → safeuploads-1.1.2}/tests/inspectors/test_gzip_inspector.py +0 -0
  81. {safeuploads-1.1.1 → safeuploads-1.1.2}/tests/inspectors/test_zip_inspector.py +0 -0
  82. {safeuploads-1.1.1 → safeuploads-1.1.2}/tests/test_audit.py +0 -0
  83. {safeuploads-1.1.1 → safeuploads-1.1.2}/tests/test_config.py +0 -0
  84. {safeuploads-1.1.1 → safeuploads-1.1.2}/tests/test_config_validation.py +0 -0
  85. {safeuploads-1.1.1 → safeuploads-1.1.2}/tests/test_enums.py +0 -0
  86. {safeuploads-1.1.1 → safeuploads-1.1.2}/tests/test_exceptions.py +0 -0
  87. {safeuploads-1.1.1 → safeuploads-1.1.2}/tests/test_fastapi_integration.py +0 -0
  88. {safeuploads-1.1.1 → safeuploads-1.1.2}/tests/test_file_validator.py +0 -0
  89. {safeuploads-1.1.1 → safeuploads-1.1.2}/tests/test_performance.py +0 -0
  90. {safeuploads-1.1.1 → safeuploads-1.1.2}/tests/test_utils.py +0 -0
  91. {safeuploads-1.1.1 → safeuploads-1.1.2}/tests/test_validate_activity_file.py +0 -0
  92. {safeuploads-1.1.1 → safeuploads-1.1.2}/tests/test_validate_gzip_file.py +0 -0
  93. {safeuploads-1.1.1 → safeuploads-1.1.2}/tests/validators/__init__.py +0 -0
  94. {safeuploads-1.1.1 → safeuploads-1.1.2}/tests/validators/test_compression_validator.py +0 -0
  95. {safeuploads-1.1.1 → safeuploads-1.1.2}/tests/validators/test_extension_validator.py +0 -0
  96. {safeuploads-1.1.1 → safeuploads-1.1.2}/tests/validators/test_unicode_validator.py +0 -0
  97. {safeuploads-1.1.1 → safeuploads-1.1.2}/tests/validators/test_windows_validator.py +0 -0
  98. {safeuploads-1.1.1 → safeuploads-1.1.2}/tests/validators/test_xml_validator.py +0 -0
@@ -39,7 +39,7 @@ jobs:
39
39
  fetch-depth: 1
40
40
 
41
41
  - name: Install uv
42
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
42
+ uses: astral-sh/setup-uv@18d369b23da25a81e9458561248e1aafff6a70fa # v10.3.1
43
43
  with:
44
44
  # Resolve uv from `[tool.uv] required-version` in pyproject.toml, so CI
45
45
  # and local development are held to the same floor and ceiling.
@@ -22,8 +22,13 @@ jobs:
22
22
  fetch-depth: 0
23
23
 
24
24
  - name: Validate PR title
25
- # The PR title is passed through an environment variable to prevent
26
- # shell injection via crafted titles (see security-and-owasp guidelines).
25
+ # The title only changes on opened/edited/reopened. Skipping it on
26
+ # `synchronize` keeps a push to a branch shared with another open PR
27
+ # (for example a WIP umbrella PR) from failing on that PR's title
28
+ # before the commit-range check below can run.
29
+ if: github.event.action != 'synchronize'
30
+ # The PR title is untrusted data: passed through an environment variable
31
+ # (never interpolated into the shell) to the trusted base-ref checker.
27
32
  env:
28
33
  PR_TITLE: ${{ github.event.pull_request.title }}
29
34
  run: |
@@ -40,7 +40,7 @@ jobs:
40
40
  fetch-depth: 1
41
41
 
42
42
  - name: Install uv
43
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
43
+ uses: astral-sh/setup-uv@18d369b23da25a81e9458561248e1aafff6a70fa # v10.3.1
44
44
  with:
45
45
  # Resolve uv from `[tool.uv] required-version` in pyproject.toml, so CI
46
46
  # and local development are held to the same floor and ceiling.
@@ -78,4 +78,4 @@ jobs:
78
78
  steps:
79
79
  - name: Deploy to GitHub Pages
80
80
  id: deployment
81
- uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0
81
+ uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 # v5.0.1
@@ -28,7 +28,7 @@ jobs:
28
28
  run: sudo apt-get update && sudo apt-get install -y libmagic1
29
29
 
30
30
  - name: Install uv
31
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
31
+ uses: astral-sh/setup-uv@18d369b23da25a81e9458561248e1aafff6a70fa # v10.3.1
32
32
  with:
33
33
  version-file: pyproject.toml
34
34
 
@@ -32,7 +32,7 @@ jobs:
32
32
  fetch-depth: 1
33
33
 
34
34
  - name: Install uv
35
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
35
+ uses: astral-sh/setup-uv@18d369b23da25a81e9458561248e1aafff6a70fa # v10.3.1
36
36
  with:
37
37
  # Resolve uv from `[tool.uv] required-version` in pyproject.toml, so CI
38
38
  # and local development are held to the same floor and ceiling.
@@ -68,7 +68,7 @@ jobs:
68
68
  run: sudo apt-get update && sudo apt-get install -y libmagic1
69
69
 
70
70
  - name: Install uv
71
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
71
+ uses: astral-sh/setup-uv@18d369b23da25a81e9458561248e1aafff6a70fa # v10.3.1
72
72
  with:
73
73
  version-file: pyproject.toml
74
74
 
@@ -82,7 +82,7 @@ jobs:
82
82
  run: uv run pytest --cov-fail-under=90
83
83
 
84
84
  - name: Upload coverage report
85
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
85
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
86
86
  if: always()
87
87
  with:
88
88
  name: safeuploads-coverage
@@ -36,7 +36,7 @@ jobs:
36
36
  persist-credentials: false
37
37
 
38
38
  - name: Install uv
39
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
39
+ uses: astral-sh/setup-uv@18d369b23da25a81e9458561248e1aafff6a70fa # v10.3.1
40
40
  with:
41
41
  # Resolve uv from `[tool.uv] required-version` in pyproject.toml, so CI
42
42
  # and local development are held to the same floor and ceiling.
@@ -122,7 +122,7 @@ jobs:
122
122
  # attests everything it downloads, so a stray checksum or SBOM file there
123
123
  # would end up in the attestation.
124
124
  - name: Upload build artifacts
125
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
125
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
126
126
  with:
127
127
  name: safeuploads-dist
128
128
  path: dist/
@@ -130,7 +130,7 @@ jobs:
130
130
  retention-days: 90
131
131
 
132
132
  - name: Upload release metadata
133
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
133
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
134
134
  with:
135
135
  name: safeuploads-release-metadata
136
136
  path: release-metadata/
@@ -149,22 +149,22 @@ jobs:
149
149
  id-token: write
150
150
  steps:
151
151
  - name: Install uv
152
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
152
+ uses: astral-sh/setup-uv@18d369b23da25a81e9458561248e1aafff6a70fa # v10.3.1
153
153
  with:
154
154
  # This job never checks the repository out, so there is no
155
155
  # pyproject.toml to read `required-version` from; keep this in step
156
156
  # with the floor declared there.
157
- version: "0.12.5"
157
+ version: "0.13.5"
158
158
  enable-cache: false
159
159
 
160
160
  - name: Download build artifacts
161
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
161
+ uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
162
162
  with:
163
163
  name: safeuploads-dist
164
164
  path: dist/
165
165
 
166
166
  - name: Generate PEP 740 attestations
167
- uses: astral-sh/attest-action@f589a42a7efb6fe400b4f400de60b4bc90390027 # v0.0.6
167
+ uses: astral-sh/attest-action@39b6ce43875c196a579e31635b11aa2a2036384a # v0.0.7
168
168
 
169
169
  - name: Publish to PyPI
170
170
  run: uv publish --trusted-publishing always dist/*.whl dist/*.tar.gz
@@ -0,0 +1,104 @@
1
+ name: Test matrix safeuploads
2
+
3
+ # Portability matrix on top of the fast default `Lint & Test` workflow:
4
+ # * every supported Python version (3.13, 3.14, 3.15) with the full
5
+ # dependency set (dev group + fastapi extra), proving the suite
6
+ # passes on every Python the package declares support for; and
7
+ # * a bare `import safeuploads` with only the base dependencies
8
+ # installed (no optional extras, no dev group), proving
9
+ # python-magic and defusedxml are truly sufficient on their own
10
+ # and the `fastapi` extra stays optional.
11
+
12
+ on:
13
+ push:
14
+ branches:
15
+ - main
16
+ paths: &paths
17
+ - safeuploads/**
18
+ - tests/**
19
+ - pyproject.toml
20
+ - uv.lock
21
+ - .github/workflows/test-matrix-safeuploads.yml
22
+ - .github/scripts/smoke_import.py
23
+ pull_request:
24
+ branches:
25
+ - main
26
+ paths: *paths
27
+
28
+ permissions:
29
+ contents: read
30
+
31
+ concurrency:
32
+ group: ${{ github.workflow }}-${{ github.ref }}
33
+ cancel-in-progress: true
34
+
35
+ jobs:
36
+ # 1. Every supported Python version, with the full dependency set.
37
+ test-python-matrix:
38
+ name: safeuploads (py${{ matrix.python }})
39
+ runs-on: ubuntu-latest
40
+ strategy:
41
+ fail-fast: false
42
+ matrix:
43
+ python: ["3.13", "3.14", "3.15"]
44
+ steps:
45
+ - name: Checkout code
46
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
47
+ with:
48
+ fetch-depth: 1
49
+
50
+ - name: Install system dependencies
51
+ run: sudo apt-get update && sudo apt-get install -y libmagic1
52
+
53
+ - name: Install uv
54
+ uses: astral-sh/setup-uv@18d369b23da25a81e9458561248e1aafff6a70fa # v10.3.1
55
+ with:
56
+ # Resolve uv from `[tool.uv] required-version` in pyproject.toml, so CI
57
+ # and local development are held to the same floor and ceiling.
58
+ version-file: pyproject.toml
59
+
60
+ - name: Sync dependencies
61
+ run: uv sync --frozen --dev --extra fastapi --python ${{ matrix.python }}
62
+
63
+ - name: Run tests
64
+ run: uv run --no-sync --python ${{ matrix.python }} pytest
65
+
66
+ # 2. Bare import with only the base dependencies (no extras, no dev group):
67
+ # proves `import safeuploads` works with zero extras installed.
68
+ import-base-deps:
69
+ name: safeuploads (bare import, no extras)
70
+ runs-on: ubuntu-latest
71
+ steps:
72
+ - name: Checkout code
73
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
74
+ with:
75
+ fetch-depth: 1
76
+
77
+ - name: Install system dependencies
78
+ run: sudo apt-get update && sudo apt-get install -y libmagic1
79
+
80
+ - name: Install uv
81
+ uses: astral-sh/setup-uv@18d369b23da25a81e9458561248e1aafff6a70fa # v10.3.1
82
+ with:
83
+ # Resolve uv from `[tool.uv] required-version` in pyproject.toml, so CI
84
+ # and local development are held to the same floor and ceiling.
85
+ version-file: pyproject.toml
86
+
87
+ - name: Install base dependencies only (no optional extras, no dev group)
88
+ # --no-dev installs the base runtime dependencies + the project only;
89
+ # the fastapi extra and the dev dependency group stay out.
90
+ # --no-editable installs safeuploads as a real distribution (not a
91
+ # path into the checkout), so the smoke test actually validates an
92
+ # install.
93
+ run: uv sync --frozen --no-dev --no-editable
94
+
95
+ # Run from outside the repository root so the local `safeuploads/`
96
+ # package directory cannot shadow the installed distribution:
97
+ # otherwise this would validate the working tree rather than what a
98
+ # user actually gets.
99
+ - name: Import safeuploads without optional extras
100
+ run: |
101
+ set -euo pipefail
102
+ cp -r .venv "$RUNNER_TEMP/base-venv"
103
+ cd "$RUNNER_TEMP"
104
+ VIRTUAL_ENV="$RUNNER_TEMP/base-venv" uv run --no-project python "$GITHUB_WORKSPACE/.github/scripts/smoke_import.py"
@@ -0,0 +1,114 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [1.1.2] - 2026-10-22
8
+
9
+ ### Changed
10
+
11
+ - Updated all dependency groups to their latest versions.
12
+ - Updated uv to 0.13.5.
13
+ - Updated GitHub Actions to their latest releases, pinned by commit hash.
14
+
15
+ ## [1.1.1] - 2026-08-19
16
+
17
+ ### Changed
18
+
19
+ - Migrated CI/CD from Forgejo/Codeberg to GitHub Actions: lint & test, scheduled fuzz, docs deploy, PyPI publish, and Conventional Commits checks.
20
+ - Added Dependabot configuration, a `CODEOWNERS` file, and a scheduled dependency-vulnerability audit workflow (`pip-audit`).
21
+ - Updated all repository, documentation, and badge links from Codeberg to GitHub.
22
+
23
+ ## [1.1.0] - 2026-07-20
24
+
25
+
26
+ ### Added
27
+
28
+ - `verify_zip_decompression` option that decompresses every ZIP entry to reject archives with forged central-directory metadata.
29
+ - Custom `executor` parameter on `FileValidator` to offload blocking inspection to a bounded thread pool instead of the default `asyncio` pool.
30
+ - Instance-level configuration validation and isolation so a per-instance `limits` object never mutates the shared class defaults.
31
+ - New `SecurityLimits` size limits plus additional recursable-archive types and script patterns for deeper threat detection.
32
+ - `BaseInspector` base class sharing configuration and audit state across inspectors.
33
+ - PEP 561 `py.typed` marker so downstream projects consume the shipped type hints.
34
+ - Integration tests exercising a real Starlette `UploadFile` and an end-to-end FastAPI multipart request.
35
+
36
+ ### Changed
37
+
38
+ - `ErrorCode` is now a `StrEnum`. This is backward compatible: members still compare and hash equal to their string values, so existing comparisons and JSON serialization are unaffected.
39
+ - Validation flow refactored around a single generic runner for consistent audit logging and error mapping.
40
+ - Thread safety hardened: access to the shared `python-magic` instance is locked, and blocking inspection is offloaded off the event loop.
41
+ - File-size validation now rejects uploads whose declared size already exceeds the limit and verifies the real byte count by streaming.
42
+ - **Potentially breaking:** the public allow-list constants (`ALLOWED_IMAGE_MIMES`, `ALLOWED_ZIP_MIMES`, `ALLOWED_IMAGE_EXTENSIONS`, `ALLOWED_ZIP_EXTENSIONS`) are now immutable `frozenset`s. Read-only use is unaffected; in-place mutation (e.g. `.add(...)`) is no longer supported, assign a new set instead.
43
+
44
+ ### Fixed
45
+
46
+ - Corrected the filename-sanitization debug log so it reports the true original filename rather than the already-sanitized value.
47
+ - Documentation URLs updated to the new site.
48
+
49
+ ## [1.0.1] - 2026-06-03
50
+
51
+ ### Fixed
52
+
53
+ - `_stream_to_temp_file` now seeks the original `UploadFile` back to position 0 (#3).
54
+
55
+ ### Changed
56
+
57
+ - Dependency version bumps.
58
+
59
+ ## [1.0.0] - 2026-03-26
60
+
61
+ First stable, production-ready release. Every layer of the validation
62
+ pipeline was expanded, hardened, and documented since v0.1.2.
63
+
64
+ ### Added
65
+
66
+ - **Activity & gzip validation:** `validate_activity_file` (GPX/TCX/FIT) and `validate_gzip_file` with decompression-bomb detection, plus `XmlSecurityValidator` using `defusedxml` to block XXE, DTD, and entity-expansion attacks in XML-based activity files.
67
+ - **Audit logging:** `SecurityAuditLogger`, `AuditEvent`, and `AuditEventType` with per-request correlation IDs, toggled by `enable_audit_logging`.
68
+ - **Content security inspector:** `ContentSecurityInspector` for malware-signature scanning, script/webshell marker detection, and polyglot detection, controlled by `enable_content_analysis` and `content_scan_max_size`.
69
+ - **Nested ZIP complexity checks:** recursive inspection with cumulative entry, depth, hash, and timing checks, archive-quine and ZIP-of-ZIPs detection, and a new `max_total_entries_recursive` limit.
70
+
71
+ ### Changed
72
+
73
+ - **Security hardening:** streaming file-size enforcement via `chunk_size`, tightened ZIP inspection (null-byte filename detection, monotonic timers, 512-byte content scans, sanitized error messages), and a hardened MIME cache (256 → 64 entries, extension-only derivation).
74
+ - `defusedxml` added as a runtime dependency.
75
+ - FastAPI example now binds to `127.0.0.1` instead of `0.0.0.0`.
76
+ - **Performance:** pre-computed `frozenset` collections, cached lookup sets at initialization, and LRU-cached MIME guessing.
77
+
78
+ ### Other
79
+
80
+ - Hypothesis fuzz tests and integration suites; GitHub Actions for lint/test, fuzzing, docs, and PyPI publish; Dependabot and `CODEOWNERS`; new security docs (threat model, architecture, integration checklist).
81
+
82
+ ## [0.1.2] - 2025-10-31
83
+
84
+ ### Fixed
85
+
86
+ - Added `BinaryFileCategory` to the exported enums in `safeuploads/__init__.py` so it is available for external use.
87
+
88
+ ## [0.1.1] - 2025-10-31
89
+
90
+ ### Added
91
+
92
+ - `max_number_files_same_type` in `SecurityLimits`; `ZipContentInspector` now uses this configurable limit instead of a hardcoded value when checking for excessive files of the same type in a ZIP archive.
93
+ - `BinaryFileCategory` enum categorizing binary file extensions (starting with fitness files such as `.fit`); `ZipContentInspector` skips script-content checks for these binary files.
94
+
95
+ ## [0.1.0] - 2025-10-30
96
+
97
+ Initial release.
98
+
99
+ ### Added
100
+
101
+ - **Filename security:** Unicode normalization, directory-traversal protection, Windows reserved-name blocking.
102
+ - **Extension validation:** configurable allow/block lists with dangerous-extension detection.
103
+ - **ZIP bomb protection:** compression-ratio limits, nested-archive inspection, size constraints.
104
+ - **MIME type verification:** magic-number validation for common file types.
105
+ - Framework-agnostic async validation, a rich exception hierarchy with machine-readable error codes, secure defaults, and full type hints.
106
+
107
+ [1.1.2]: https://github.com/endurain-project/safeuploads/compare/v1.1.1...v1.1.2
108
+ [1.1.1]: https://github.com/endurain-project/safeuploads/compare/v1.1.0...v1.1.1
109
+ [1.1.0]: https://github.com/endurain-project/safeuploads/compare/v1.0.1...v1.1.0
110
+ [1.0.1]: https://github.com/endurain-project/safeuploads/releases/tag/v1.0.1
111
+ [1.0.0]: https://github.com/endurain-project/safeuploads/releases/tag/v1.0.0
112
+ [0.1.2]: https://github.com/endurain-project/safeuploads/releases/tag/v0.1.2
113
+ [0.1.1]: https://github.com/endurain-project/safeuploads/releases/tag/v0.1.1
114
+ [0.1.0]: https://github.com/endurain-project/safeuploads/releases/tag/v0.1.0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: safeuploads
3
- Version: 1.1.1
3
+ Version: 1.1.2
4
4
  Summary: A comprehensive file security system for validating uploads and preventing attacks
5
5
  Author-email: João Vitória Silva <joao@endurain.com>
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "safeuploads"
3
- version = "1.1.1"
3
+ version = "1.1.2"
4
4
  description = "A comprehensive file security system for validating uploads and preventing attacks"
5
5
  authors = [
6
6
  {name = "João Vitória Silva",email = "joao@endurain.com"}
@@ -40,7 +40,7 @@ requires = ["hatchling"]
40
40
  build-backend = "hatchling.build"
41
41
 
42
42
  [tool.uv]
43
- required-version = "0.12.5"
43
+ required-version = "0.13.5"
44
44
  exclude-newer = "30 days"
45
45
 
46
46
  [tool.ruff]