security: rate limit expensive routes, stop upload path traversal - #161
Open
NetworkTheoryAppliedResearchInstitute wants to merge 1 commit into
Open
NetworkTheoryAppliedResearchInstitute wants to merge 1 commit into
NetworkTheoryAppliedResearchInstitute wants to merge 1 commit into
Conversation
Clears the nine open CodeQL alerts that #148 does not cover. js/path-injection (backend/models/message.js:31): file.name arrives from the client and was concatenated straight into the upload path, so a name like '../../etc/passwd' wrote outside UPLOAD_DIR. Collapse the name with path.basename, strip anything outside [A-Za-z0-9._-] (which also removes NUL bytes and leading dots), and refuse the write if the resolved path is not directly inside UPLOAD_DIR. js/missing-rate-limiting (8 alerts): add express-rate-limit and a shared backend/middleware/rateLimit.js exposing three ceilings per 15m window -- apiLimiter (600), writeLimiter (60) and uploadLimiter (20). Applied at router level via .use() rather than as an extra route argument, so the existing two-argument route signatures are untouched. server.js takes the global apiLimiter ahead of authMiddleware so unauthenticated floods are shed before auth work happens. actions/missing-workflow-permissions: check-hardcoded-urls.yml now declares contents: read. express-rate-limit was added with --package-lock-only so the three tracked stub files under backend/node_modules are left intact, and a matching express-rate-limit stub joins them (force-added, since backend/.gitignore ignores node_modules/) so `npm test` still runs without a full install. backend suite: 6/6 pass, unchanged from before the patch. Signed-off-by: Jodson Graves <info@ntari.org> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Replaces #159, which had a DCO failure (sign-off name did not match the commit author). Same changes, rebased onto current
mainand correctly signed off as a single commit.Clears the nine open CodeQL alerts on
mainthat #148 did not cover. With this merged, Agrinet's code-scanning queue goes to zero.What was wrong
js/path-injection—backend/models/message.js:31.file.namecomes from the client and was concatenated straight into the write path:A message with
file.name = "../../etc/passwd"wrote outsideUPLOAD_DIR. Now the name is collapsed withpath.basename, stripped to[A-Za-z0-9._-](which also removes NUL bytes and leading dots), and the write is refused if the resolved path is not directly insideUPLOAD_DIR.Checked against
photo.png,../../etc/passwd,..%2f..%2fetc,....//....//x,a/b/c.png,../.ssh/authorized_keys,\0evil.sh,"",null,..,.....— every one stays inside the directory.js/missing-rate-limiting— 8 alerts. No limiter existed anywhere. Addsexpress-rate-limitandbackend/middleware/rateLimit.jswith three ceilings per 15-minute window:apiLimiterserver.js, plus agrotourism readswriteLimiteruploadLimiterPOST /create(up to 5 images)The global limiter sits ahead of
authMiddlewareso unauthenticated floods are shed before any auth work happens.actions/missing-workflow-permissions.check-hardcoded-urls.ymlnow declarescontents: read.Notes for review
.use(), not as an extra route argument. The trackedexpressstub registers routes as(path, handler)— inserting a third argument would have silently dropped the real handler.express-rate-limitwas added with--package-lock-onlyso the three tracked stubs underbackend/node_modulesare untouched. A matching stub joins them (force-added, sincebackend/.gitignore:26ignoresnode_modules/) sonpm testruns without a full install.Verification
npm testinbackend/: 6/6 pass, identical to the pre-patch baseline, re-run after rebasing onto currentmain.node --checkclean on all eight touched JS files.🤖 Generated with Claude Code