Files
cannamanage/docs/sprint-3/snyk-code-results-phase4-7.json
T
Patrick Plate fe6e96dd3f feat: Sprint 4 complete — frontend MVP (admin dashboard + member portal)
Shadboard starter-kit (Next.js 15 + React 19 + shadcn/ui + Tailwind 4)

Sprint 4.a — Admin Dashboard:
- Auth: NextAuth.js v5, login page, middleware, token rotation
- Dashboard: KPI cards, Recharts stock chart, quick actions
- Members: TanStack Table (search/sort/paginate), add/edit forms
- Distributions: multi-step form, real-time quota check, history
- Stock: batch management, recall dialog, bar chart
- Reports: monthly/member-list/recall, PDF/CSV download, preview

Sprint 4.b — Member Portal:
- Separate route group with top-nav layout (mobile-first)
- Quota dashboard with radial SVG progress indicators
- Distribution history with month filter
- Profile/settings with password change

Cross-cutting:
- i18n: German (default) + English via next-intl
- Dark + light mode (next-themes, user-togglable)
- Playwright E2E tests (6/6 green)
- Docker multi-stage build (node:22-alpine)
- API proxy via Next.js rewrites

Tech: Next.js 15.2.8, React 19, Tailwind 4, NextAuth v5,
TanStack Table, Recharts, Zod, React Hook Form, Playwright
2026-06-12 17:18:38 +02:00

2 lines
20 KiB
JSON

{"$schema": "https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/schemas/sarif-schema-2.1.0.json","version": "2.1.0","runs": [{"tool": {"driver" : {"name" : "SnykCode","semanticVersion" : "1.1305.1","version" : "1.1305.1","informationUri" : "https://docs.snyk.io/","rules" : [{"id": "java/DisablesCSRFProtection","name": "DisablesCSRFProtection","shortDescription": {"text": "Cross-Site Request Forgery (CSRF)"},"defaultConfiguration": {"level": "error"},"help": {"markdown": "\n## Details\nCross-site request forgery is an attack in which a malicious third party takes advantage of a user's authenticated credentials (such as a browser cookie) to impersonate that trusted user and perform unauthorized actions. The web application server cannot tell the difference between legitimate and malicious requests. This type of attack generally begins by tricking the user with a social engineering attack, such as a link or popup that the user inadvertently clicks, causing an unauthorized request to be sent to the web server. Consequences vary: At a standard user level, attackers can change passwords, transfer funds, make purchases, or connect with contacts; from an administrator account, attackers can then make changes to or even take down the app itself.\n\n## Best practices for prevention\n* Use development frameworks that defend against CSRF, using a nonce, hash, or some other security device to the URL and/or to forms.\n* Implement secure, unique, hidden tokens that are checked by the server each time to validate state-change requests.\n* Never assume that authentication tokens and session identifiers mean a request is legitimate.\n* Understand and implement other safe-cookie techniques, such as double submit cookies.\n* Terminate user sessions when not in use, including automatic timeout.\n* Ensure rigorous coding practices and defenses against other commonly exploited CWEs, since cross-site scripting (XSS), for example, can be used to bypass defenses against CSRF.","text": ""},"properties": {"tags": ["java","DisablesCSRFProtection","Security"],"categories": ["Security"],"exampleCommitFixes": [{"commitURL": "https://github.com/13482477/JFDF/commit/3326a94a203ab334e9185d93beadc38b9c93b100?diff=split#diff-a9f9136673bc42f9fcd901899a430de1862ad2f7cda4150ce17bbddbd5909851L-1","lines": [{"line": "http\r\n","lineNumber": 37,"lineChange": "none"},{"line": ".authorizeRequests()\r\n","lineNumber": 38,"lineChange": "none"},{"line": "\t.antMatchers(new String[] {\r\n","lineNumber": 39,"lineChange": "none"},{"line": "\t\t\t\"/login\",\r\n","lineNumber": 40,"lineChange": "none"},{"line": "\t\t\t\"/logout\",\r\n","lineNumber": 41,"lineChange": "none"},{"line": "\t\t\t\"/**/*.css\",\r\n","lineNumber": 42,"lineChange": "none"},{"line": "\t\t\t\"/**/*.js\",\r\n","lineNumber": 43,"lineChange": "none"},{"line": "\t\t\t\"/**/*.woff\",\r\n","lineNumber": 44,"lineChange": "none"},{"line": "\t\t\t\"/**/*.woff2\",\r\n","lineNumber": 45,"lineChange": "none"},{"line": "\t\t\t\"/**/*.css.map\",\r\n","lineNumber": 46,"lineChange": "none"},{"line": "\t\t\t\"/**/*.ttf\",\r\n","lineNumber": 47,"lineChange": "none"},{"line": "\t\t\t\"/**/*.png\",\r\n","lineNumber": 48,"lineChange": "none"},{"line": "\t\t\t\"/**/*.jpg\",\r\n","lineNumber": 49,"lineChange": "none"},{"line": "\t\t\t\"/**/*.jpeg\",\r\n","lineNumber": 50,"lineChange": "none"},{"line": "\t\t\t\"/**/*.gif\",\r\n","lineNumber": 51,"lineChange": "none"},{"line": "\t\t\t}).permitAll()\r\n","lineNumber": 52,"lineChange": "none"},{"line": "\t.anyRequest().authenticated()\r\n","lineNumber": 53,"lineChange": "none"},{"line": "\t.and()\r\n","lineNumber": 54,"lineChange": "none"},{"line": ".formLogin()\r\n","lineNumber": 55,"lineChange": "none"},{"line": "\t.loginPage(\"/login\")\r\n","lineNumber": 56,"lineChange": "none"},{"line": "\t.defaultSuccessUrl(\"/index\")\r\n","lineNumber": 57,"lineChange": "none"},{"line": "\t.failureHandler(new FeedbackLoginInfoAuthenticationFailureHandler(\"/login\"))\r\n","lineNumber": 58,"lineChange": "none"},{"line": "\t.and()\r\n","lineNumber": 59,"lineChange": "none"},{"line": ".logout()\r\n","lineNumber": 60,"lineChange": "none"},{"line": "\t.logoutUrl(\"/logout\")\r\n","lineNumber": 61,"lineChange": "none"},{"line": "\t.logoutSuccessUrl(\"/login\")\r\n","lineNumber": 62,"lineChange": "none"},{"line": "\t.and()\r\n","lineNumber": 63,"lineChange": "none"},{"line": ".csrf()\r\n","lineNumber": 64,"lineChange": "removed"},{"line": "\t.disable();\r\n","lineNumber": 65,"lineChange": "removed"},{"line": ".csrf();\r\n","lineNumber": 64,"lineChange": "added"}]},{"commitURL": "https://github.com/mraible/java-webapp-security-examples/commit/1ae83aeb6975a107dcdb616eeae63bc846fcadaf?diff=split#diff-b8cb20d5732c784ae693cb1cd9ecb813e912a21fe570c581998875276a2a642dL-1","lines": [{"line": "http\n","lineNumber": 23,"lineChange": "none"},{"line": " .csrf().disable()\n","lineNumber": 24,"lineChange": "removed"},{"line": " .csrf().and()\n","lineNumber": 24,"lineChange": "added"}]},{"commitURL": "https://github.com/jgribonvald/demo-spring-security-cas/commit/3b1ee5ecc5e718513127355b884c165bb4936c7f?diff=split#diff-4ead997b1df6dd1b785b7ba2dbcb18dfb6f6624a1997e5642b016adf46e69d08L-1","lines": [{"line": "\t\t/**\n","lineNumber": 162,"lineChange": "removed"},{"line": "\t\t * <session-management session-fixation-protection=\"newSession\"/>\n","lineNumber": 163,"lineChange": "removed"},{"line": "\t\t */\n","lineNumber": 164,"lineChange": "removed"},{"line": "\t\thttp.sessionManagement().sessionFixation().changeSessionId();\n","lineNumber": 165,"lineChange": "removed"},{"line": "\n","lineNumber": 166,"lineChange": "removed"},{"line": "\t\thttp.csrf().disable();\n","lineNumber": 167,"lineChange": "removed"},{"line": "\t\t// http.csrf();\n","lineNumber": 171,"lineChange": "added"}]}],"exampleCommitDescriptions": [],"precision": "very-high","repoDatasetSize": 42,"cwe": ["CWE-352"]}},{"id": "java/HardcodedPassword/test","name": "HardcodedPassword/test","shortDescription": {"text": "Use of Hardcoded Passwords"},"defaultConfiguration": {"level": "note"},"help": {"markdown": "\n## Details\n\nDevelopers may use hardcoded passwords during development to streamline setup or simplify authentication while testing. Although these passwords are intended to be removed before deployment, they are sometimes inadvertently left in the code. This introduces serious security risks, especially if the password grants elevated privileges or is reused across multiple systems.\n\nAn attacker who discovers a hardcoded password can potentially gain unauthorized access, escalate privileges, exfiltrate sensitive data, or disrupt service availability. If the password is reused across different environments or applications, the compromise can spread quickly and broadly.\n\n## Best practices for prevention\n* Plan software architecture such that keys and passwords are always stored outside the code, wherever possible.\n* Plan encryption into software architecture for all credential information and ensure proper handling of keys, credentials, and passwords.\n* Prompt for a secure password on first login rather than hard-code a default password.\n* If a hardcoded password or credential must be used, limit its use, for example, to system console users rather than via the network.\n* Use strong hashes for inbound password authentication, ideally with randomly assigned salts to increase the difficulty level in case of brute-force attack.","text": ""},"properties": {"tags": ["java","HardcodedPassword","Security","InTest"],"categories": ["Security","InTest"],"exampleCommitFixes": [{"commitURL": "https://github.com/clowee/OpenSZZ-Cloud-Native/commit/ee429faf9d384074cf33515eda2a52e4e85ef061?diff=split#diff-a125fdf9d37b8daa4d9f0a7a46aedd416a80a49936bdee4bae40db3f3eef22deL-1","lines": [{"line": "final String username = \"noreply.openszz@gmail.com\";\n","lineNumber": 19,"lineChange": "removed"},{"line": "final String password = \"Aa30011992\";\n","lineNumber": 20,"lineChange": "removed"},{"line": "final String username = System.getenv(\"EMAIL\");\n","lineNumber": 19,"lineChange": "added"},{"line": "final String password = System.getenv(\"PWD\");\n","lineNumber": 20,"lineChange": "added"}]},{"commitURL": "https://github.com/winstonli/writelatex-git-bridge/commit/1117c70f31cee7d9a84c565c143f353d8bbab19e?diff=split#diff-16d090e60dcd386546c2164ae454bd356cbf326d715a66796582e8c003d8af10L-1","lines": [{"line": " public static void setBasicAuth(String username, String password) {\n","lineNumber": 27,"lineChange": "added"},{"line": " USERNAME = username;\n","lineNumber": 28,"lineChange": "added"},{"line": " PASSWORD = password;\n","lineNumber": 29,"lineChange": "added"},{"line": " }\n","lineNumber": 30,"lineChange": "added"},{"line": "\n","lineNumber": 31,"lineChange": "added"},{"line": " public static void setBaseURL(String baseURL) {\n","lineNumber": 32,"lineChange": "added"},{"line": " BASE_URL = baseURL;\n","lineNumber": 33,"lineChange": "added"},{"line": " }\n","lineNumber": 34,"lineChange": "added"},{"line": "\n","lineNumber": 35,"lineChange": "added"}]},{"commitURL": "https://github.com/CheckChe0803/flink-recommandSystem-demo/commit/bbe348d12bc76858d8c0878f2a89ccc0f1e7b05b?diff=split#diff-7cac3b1a67764486d11265840a420739f0339a6cc8ff947d192de102366f8acaL-1","lines": [{"line": "private static String URL = \"jdbc:mysql://localhost/con?serverTimezone=GMT%2B8\";\n","lineNumber": 6,"lineChange": "removed"},{"line": "private static String NAME = \"root\";\n","lineNumber": 7,"lineChange": "removed"},{"line": "private static String PASS = \"root\";\n","lineNumber": 8,"lineChange": "removed"},{"line": "private static String URL = Property.getStrValue(\"mysql.url\");\n","lineNumber": 8,"lineChange": "added"},{"line": "private static String NAME = Property.getStrValue(\"mysql.name\");\n","lineNumber": 9,"lineChange": "added"},{"line": "private static String PASS = Property.getStrValue(\"mysql.pass\");\n","lineNumber": 10,"lineChange": "added"},{"line": "private static Statement stmt;\n","lineNumber": 11,"lineChange": "none"},{"line": "static {\n","lineNumber": 12,"lineChange": "none"},{"line": " try {\n","lineNumber": 13,"lineChange": "none"},{"line": " Class.forName(\"com.mysql.cj.jdbc.Driver\");\n","lineNumber": 14,"lineChange": "none"},{"line": " Connection conn = DriverManager.getConnection(URL, NAME, PASS);\n","lineNumber": 15,"lineChange": "none"}]}],"exampleCommitDescriptions": [],"precision": "very-high","repoDatasetSize": 74,"cwe": ["CWE-798","CWE-259"]}},{"id": "java/NonCryptoHardcodedSecret/test","name": "NonCryptoHardcodedSecret/test","shortDescription": {"text": "Use of Hardcoded, Security-relevant Constants"},"defaultConfiguration": {"level": "note"},"help": {"markdown": "## Details\n\nWhen constants are hardcoded into applications, this information could easily be reverse-engineered and become known to attackers. For example, if a breached authentication token is hardcoded in multiple places in the application, it may lead to components of the application remaining vulnerable if not all instances are changed.\nAnother negative effect of hard-coding constants is potential unpredictability in the application's performance if the development team fails to update every single instance of the hardcoded constant throughout the code. For these reasons, hard-coding security-relevant constants is considered bad coding practice and should be remedied if present and avoided in future.\n\n## Best practices for prevention\n* Never hard code security-related constants; use symbolic names or configuration lookup files.\n* As hard coding is often done by coders working alone on a small scale, examine all legacy code components and test carefully when scaling.\n* Adopt a \"future-proof code\" mindset: While use of constants may save a little time now and make development simpler in the short term, it could cost time and money adapting to scale or other unforeseen circumstances (such as new hardware) in the future.","text": ""},"properties": {"tags": ["java","NonCryptoHardcodedSecret","Security","InTest"],"categories": ["Security","InTest"],"exampleCommitFixes": [{"commitURL": "https://github.com/tronprotocol/java-tron/commit/84148c19e3d15f344fc164913be5bee478c1f637?diff=split#diff-9ff136527c21b19349c00267ff04c85b76dae23a2d28bc0f17a7c5b2eac78565L-1","lines": [{"line": "private String ownerAddress = \"TDZdB4ogHSgU1CGrun8WXaMb2QDDkvAKQm\";\n","lineNumber": 17,"lineChange": "removed"},{"line": "private String ownerAddress = Configuration.getByPath(\"stress.conf\").getString(\"address.exchangeOwnerAddress\");\n","lineNumber": 18,"lineChange": "added"},{"line": "private long exchangeID = commonexchangeid;\n","lineNumber": 19,"lineChange": "none"},{"line": "private long quant = 1000000L;\n","lineNumber": 20,"lineChange": "none"},{"line": "private String privateKey = \"549c7797b351e48ab1c6bb5857138b418012d97526fc2acba022357d49c93ac0\";\n","lineNumber": 20,"lineChange": "removed"},{"line": "private String privateKey = Configuration.getByPath(\"stress.conf\").getString(\"privateKey.exchangeOwnerKey\");\n","lineNumber": 21,"lineChange": "added"}]},{"commitURL": "https://github.com/shuxianfeng/movision/commit/5ee84a05bac382bea508e6a42da3330b1ccf4371?diff=split#diff-bdd70437062ccb0d3735e4c014d182875ef0c029af6c9c8c3e2a42e4136d410fL-1","lines": [{"line": " String accessKeyId = \"LTAITI0FOKgMZQty\";\n","lineNumber": 15,"lineChange": "removed"},{"line": " String accessKeySecret = \"5x12H1yASg31OlPanhTCg0z0PzNr3t\";\n","lineNumber": 16,"lineChange": "removed"},{"line": " String accessKeyId = PropertiesLoader.getValue(\"access.key.id\");\n","lineNumber": 17,"lineChange": "added"},{"line": " String accessKeySecret = PropertiesLoader.getValue(\"access.key.secret\");\n","lineNumber": 18,"lineChange": "added"},{"line": "\n","lineNumber": 19,"lineChange": "added"}]},{"commitURL": "https://github.com/xiexianbin/UEditor-for-aliyun-OSS/commit/324d6fd48c4c99d43ac30545ba30f9736b505c61?diff=split#diff-4d95e836c61d2ea3ffdda0f95df204e45f3b74f5ba58cb53c85cdb5114efa29fL-1","lines": [{"line": "static {\r\n","lineNumber": 17,"lineChange": "added"},{"line": "String OSSKeyPath = SystemUtil.getProjectClassesPath() + \"OSSKey.properties\";\r\n","lineNumber": 18,"lineChange": "added"},{"line": "// 生成文件输入流\r\n","lineNumber": 19,"lineChange": "added"},{"line": "FileInputStream inpf = null;\r\n","lineNumber": 20,"lineChange": "added"},{"line": "try {\r\n","lineNumber": 21,"lineChange": "added"},{"line": " inpf = new FileInputStream(new File(OSSKeyPath));\r\n","lineNumber": 22,"lineChange": "added"},{"line": " OSSKeyProperties.load(inpf);\r\n","lineNumber": 23,"lineChange": "added"},{"line": " useStatus = (Boolean) OSSKeyProperties.get(\"useStatus\");\r\n","lineNumber": 24,"lineChange": "added"},{"line": " key = (String) OSSKeyProperties.get(\"key\");\r\n","lineNumber": 25,"lineChange": "added"},{"line": " secret = (String) OSSKeyProperties.get(\"secret\");\r\n","lineNumber": 26,"lineChange": "added"},{"line": " endPoint = (String) OSSKeyProperties.get(\"endPoint\");\r\n","lineNumber": 27,"lineChange": "added"},{"line": "} catch (Exception e) {\r\n","lineNumber": 28,"lineChange": "added"},{"line": " e.printStackTrace();\r\n","lineNumber": 29,"lineChange": "added"},{"line": "}\r\n","lineNumber": 30,"lineChange": "added"},{"line": "}\r\n","lineNumber": 31,"lineChange": "added"}]}],"exampleCommitDescriptions": [],"precision": "very-high","repoDatasetSize": 33,"cwe": ["CWE-547"]}}]}},"results": [{"ruleId": "java/DisablesCSRFProtection","ruleIndex": 0,"level": "error","message": {"text":"CSRF protection is disabled by disable. This allows the attackers to execute requests on a user's behalf.","markdown":"CSRF protection is disabled by {0}. This allows the attackers to execute requests on a user's behalf.","arguments": ["[disable](0)"]},"locations": [{ "id": 0, "physicalLocation": {"artifactLocation": { "uri": "cannamanage-api/src/main/java/de/cannamanage/api/security/SecurityConfig.java", "uriBaseId": "%SRCROOT%"},"region": { "startLine":107, "endLine":109, "startColumn":9, "endColumn":22} }}],"fingerprints": {"identity": "e7bfa036-d8c0-453d-abd2-239ced27a331","0": "8cdfc7f3cba26ded31038c3d7c5997d64002a77944acce3357eb19ec5d77c693","1": "b5099633.fd6a5963.13c31930.e22980a8.f2a5bca1.4431cad1.7b4155dd.54d46e25.61fe6857.fd6a5963.13c31930.de031890.f0e1baa5.102e2858.3953228b.f7c40842","snyk/asset/finding/v1": "e7bfa036-d8c0-453d-abd2-239ced27a331"},"codeFlows": [{"threadFlows": [{"locations": [{"location": {"id": 0,"physicalLocation": {"artifactLocation": { "uri": "cannamanage-api/src/main/java/de/cannamanage/api/security/SecurityConfig.java", "uriBaseId": "%SRCROOT%"},"region": { "startLine":109, "endLine":109, "startColumn":31, "endColumn":43}}}}]}]}],"properties": {"isAutofixable": true,"priorityScore": 784,"priorityScoreFactors": [ {"label": true,"type": "hotFileCodeFlow" }, {"label": true,"type": "fixExamples" }]}},{"ruleId": "java/HardcodedPassword/test","ruleIndex": 1,"level": "note","message": {"text":"Do not hardcode passwords in code. Found hardcoded password used in here.","markdown":"Do not hardcode passwords in code. Found hardcoded password used in {0}.","arguments": ["[here](0)"]},"locations": [{ "id": 0, "physicalLocation": {"artifactLocation": { "uri": "cannamanage-api/src/test/java/de/cannamanage/api/controller/AuthControllerIntegrationTest.java", "uriBaseId": "%SRCROOT%"},"region": { "startLine":48, "endLine":48, "startColumn":49, "endColumn":65} }}],"fingerprints": {"0": "a7b20b1967684ddcb44b5af14789ff3f8bd7a5e89329849d356794ce1e1802e6","1": "51f4bbec.dd05ec30.c0c79380.de031890.8b2d3351.248bce3c.3f71d1e7.87dfd8cc.51f4bbec.8b9ac446.c0c79380.de031890.5b39032a.248bce3c.c66d287d.54d46e25","snyk/asset/finding/v1": "a8ecbbe1-6bb2-4f4f-9ba8-9cf1985f0f1b","identity": "a8ecbbe1-6bb2-4f4f-9ba8-9cf1985f0f1b"},"codeFlows": [{"threadFlows": [{"locations": [{"location": {"id": 0,"physicalLocation": {"artifactLocation": { "uri": "cannamanage-api/src/test/java/de/cannamanage/api/controller/AuthControllerIntegrationTest.java", "uriBaseId": "%SRCROOT%"},"region": { "startLine":48, "endLine":48, "startColumn":49, "endColumn":65}}}}]}]}],"properties": {"isAutofixable": true,"priorityScore": 384,"priorityScoreFactors": [ {"label": true,"type": "hotFileCodeFlow" }, {"label": true,"type": "fixExamples" }]}},{"ruleId": "java/NonCryptoHardcodedSecret/test","ruleIndex": 2,"level": "note","message": {"text":"Avoid hardcoding values that are meant to be secret. Found hardcoded secret.","markdown":"Avoid hardcoding values that are meant to be secret. Found hardcoded {0}.","arguments": ["[secret](0)"]},"locations": [{ "id": 0, "physicalLocation": {"artifactLocation": { "uri": "cannamanage-api/src/test/java/de/cannamanage/api/integration/AuthIntegrationTest.java", "uriBaseId": "%SRCROOT%"},"region": { "startLine":24, "endLine":24, "startColumn":50, "endColumn":65} }}],"fingerprints": {"0": "e238107ed2ee625abc912c1c7c8826f6a213bb6185a1b68af6cdad75443ac20c","1": "15d2f486.dd05ec30.bfb18340.de031890.1d579486.ce109560.e4580e17.71a2bd77.15d2f486.df378f3d.fb5ed936.de031890.1d579486.ce109560.7115c551.bdd11d5d","snyk/asset/finding/v1": "394b4f40-a965-4d48-8243-0cb1e830a4bc","identity": "394b4f40-a965-4d48-8243-0cb1e830a4bc"},"codeFlows": [{"threadFlows": [{"locations": [{"location": {"id": 0,"physicalLocation": {"artifactLocation": { "uri": "cannamanage-api/src/test/java/de/cannamanage/api/integration/AuthIntegrationTest.java", "uriBaseId": "%SRCROOT%"},"region": { "startLine":24, "endLine":24, "startColumn":50, "endColumn":65}}}}]}]}],"properties": {"isAutofixable": true,"priorityScore": 384,"priorityScoreFactors": [ {"label": true,"type": "hotFileCodeFlow" }, {"label": true,"type": "fixExamples" }]}}],"properties": {"coverage": [{"files": 122,"isSupported": true,"lang": ".java","type": "SUPPORTED"},{"files": 4,"isSupported": true,"lang": ".xml","type": "SUPPORTED"}]},"automationDetails": {"id":"Snyk/Code/2026-06-12T09:10:20Z"}}]}