openpitstop 1.0.0

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 (274) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +512 -0
  3. package/demo-repo/README.md +24 -0
  4. package/demo-repo/package-lock.json +4483 -0
  5. package/demo-repo/package.json +17 -0
  6. package/demo-repo/src/config.js +5 -0
  7. package/demo-repo/src/db.js +31 -0
  8. package/demo-repo/src/server.js +13 -0
  9. package/demo-repo/src/userController.js +22 -0
  10. package/demo-repo/src/userRepo.js +18 -0
  11. package/demo-repo/src/userService.js +59 -0
  12. package/demo-repo/test/user.test.js +12 -0
  13. package/demo-repo-fintech/README.md +27 -0
  14. package/demo-repo-fintech/package-lock.json +1023 -0
  15. package/demo-repo-fintech/package.json +14 -0
  16. package/demo-repo-fintech/pitstop-repro-ledger-order-ord-conc-1-charged-2.test.mjs +175 -0
  17. package/demo-repo-fintech/pitstop-repro-ledger-order-ord-retry-2-charged-2.test.mjs +175 -0
  18. package/demo-repo-fintech/pitstop-repro-ledger-order-ord-webhook-3-charged-2.test.mjs +175 -0
  19. package/demo-repo-fintech/src/gateway.js +26 -0
  20. package/demo-repo-fintech/src/server.js +61 -0
  21. package/demo-repo-generators/package-lock.json +1508 -0
  22. package/demo-repo-generators/package.json +17 -0
  23. package/demo-repo-generators/public/index.html +10 -0
  24. package/demo-repo-generators/scripts/build.js +17 -0
  25. package/demo-repo-generators/src/counter.js +16 -0
  26. package/demo-repo-integrity/README.md +49 -0
  27. package/demo-repo-integrity/package.json +12 -0
  28. package/demo-repo-integrity/src/money.js +19 -0
  29. package/demo-repo-integrity/test/money.test.js +17 -0
  30. package/dist/analyzers/accessibility.d.ts +18 -0
  31. package/dist/analyzers/accessibility.js +248 -0
  32. package/dist/analyzers/accessibility.js.map +1 -0
  33. package/dist/analyzers/dependencyGraph.d.ts +14 -0
  34. package/dist/analyzers/dependencyGraph.js +206 -0
  35. package/dist/analyzers/dependencyGraph.js.map +1 -0
  36. package/dist/analyzers/devex.d.ts +19 -0
  37. package/dist/analyzers/devex.js +301 -0
  38. package/dist/analyzers/devex.js.map +1 -0
  39. package/dist/analyzers/duplication.d.ts +2 -0
  40. package/dist/analyzers/duplication.js +47 -0
  41. package/dist/analyzers/duplication.js.map +1 -0
  42. package/dist/analyzers/index.d.ts +12 -0
  43. package/dist/analyzers/index.js +38 -0
  44. package/dist/analyzers/index.js.map +1 -0
  45. package/dist/analyzers/integrity/assertionLiteralTamper.d.ts +2 -0
  46. package/dist/analyzers/integrity/assertionLiteralTamper.js +164 -0
  47. package/dist/analyzers/integrity/assertionLiteralTamper.js.map +1 -0
  48. package/dist/analyzers/integrity/exceptionSwallow.d.ts +2 -0
  49. package/dist/analyzers/integrity/exceptionSwallow.js +198 -0
  50. package/dist/analyzers/integrity/exceptionSwallow.js.map +1 -0
  51. package/dist/analyzers/integrity/exitCheat.d.ts +2 -0
  52. package/dist/analyzers/integrity/exitCheat.js +31 -0
  53. package/dist/analyzers/integrity/exitCheat.js.map +1 -0
  54. package/dist/analyzers/integrity/git.d.ts +10 -0
  55. package/dist/analyzers/integrity/git.js +181 -0
  56. package/dist/analyzers/integrity/git.js.map +1 -0
  57. package/dist/analyzers/integrity/hardcodedMatch.d.ts +2 -0
  58. package/dist/analyzers/integrity/hardcodedMatch.js +93 -0
  59. package/dist/analyzers/integrity/hardcodedMatch.js.map +1 -0
  60. package/dist/analyzers/integrity/helpers.d.ts +21 -0
  61. package/dist/analyzers/integrity/helpers.js +66 -0
  62. package/dist/analyzers/integrity/helpers.js.map +1 -0
  63. package/dist/analyzers/integrity/index.d.ts +10 -0
  64. package/dist/analyzers/integrity/index.js +27 -0
  65. package/dist/analyzers/integrity/index.js.map +1 -0
  66. package/dist/analyzers/integrity/mockOverreach.d.ts +2 -0
  67. package/dist/analyzers/integrity/mockOverreach.js +72 -0
  68. package/dist/analyzers/integrity/mockOverreach.js.map +1 -0
  69. package/dist/analyzers/integrity/suppressionCreep.d.ts +2 -0
  70. package/dist/analyzers/integrity/suppressionCreep.js +27 -0
  71. package/dist/analyzers/integrity/suppressionCreep.js.map +1 -0
  72. package/dist/analyzers/integrity/testTamper.d.ts +2 -0
  73. package/dist/analyzers/integrity/testTamper.js +153 -0
  74. package/dist/analyzers/integrity/testTamper.js.map +1 -0
  75. package/dist/analyzers/integrity/types.d.ts +63 -0
  76. package/dist/analyzers/integrity/types.js +13 -0
  77. package/dist/analyzers/integrity/types.js.map +1 -0
  78. package/dist/analyzers/ledger/attacks.d.ts +17 -0
  79. package/dist/analyzers/ledger/attacks.js +135 -0
  80. package/dist/analyzers/ledger/attacks.js.map +1 -0
  81. package/dist/analyzers/ledger/discover.d.ts +15 -0
  82. package/dist/analyzers/ledger/discover.js +122 -0
  83. package/dist/analyzers/ledger/discover.js.map +1 -0
  84. package/dist/analyzers/ledger/evidence.d.ts +22 -0
  85. package/dist/analyzers/ledger/evidence.js +127 -0
  86. package/dist/analyzers/ledger/evidence.js.map +1 -0
  87. package/dist/analyzers/ledger/harness.d.ts +4 -0
  88. package/dist/analyzers/ledger/harness.js +270 -0
  89. package/dist/analyzers/ledger/harness.js.map +1 -0
  90. package/dist/analyzers/ledger/index.d.ts +14 -0
  91. package/dist/analyzers/ledger/index.js +116 -0
  92. package/dist/analyzers/ledger/index.js.map +1 -0
  93. package/dist/analyzers/ledger/types.d.ts +31 -0
  94. package/dist/analyzers/ledger/types.js +2 -0
  95. package/dist/analyzers/ledger/types.js.map +1 -0
  96. package/dist/analyzers/perf.d.ts +2 -0
  97. package/dist/analyzers/perf.js +106 -0
  98. package/dist/analyzers/perf.js.map +1 -0
  99. package/dist/analyzers/reliability.d.ts +22 -0
  100. package/dist/analyzers/reliability.js +339 -0
  101. package/dist/analyzers/reliability.js.map +1 -0
  102. package/dist/analyzers/routes.d.ts +17 -0
  103. package/dist/analyzers/routes.js +115 -0
  104. package/dist/analyzers/routes.js.map +1 -0
  105. package/dist/analyzers/security.d.ts +2 -0
  106. package/dist/analyzers/security.js +302 -0
  107. package/dist/analyzers/security.js.map +1 -0
  108. package/dist/analyzers/suiteRunner.d.ts +64 -0
  109. package/dist/analyzers/suiteRunner.js +381 -0
  110. package/dist/analyzers/suiteRunner.js.map +1 -0
  111. package/dist/analyzers/tests.d.ts +2 -0
  112. package/dist/analyzers/tests.js +215 -0
  113. package/dist/analyzers/tests.js.map +1 -0
  114. package/dist/analyzers/types.d.ts +203 -0
  115. package/dist/analyzers/types.js +2 -0
  116. package/dist/analyzers/types.js.map +1 -0
  117. package/dist/analyzers/util.d.ts +35 -0
  118. package/dist/analyzers/util.js +209 -0
  119. package/dist/analyzers/util.js.map +1 -0
  120. package/dist/ciCheckA.d.ts +2 -0
  121. package/dist/ciCheckA.js +5 -0
  122. package/dist/ciCheckA.js.map +1 -0
  123. package/dist/ciCheckB.d.ts +2 -0
  124. package/dist/ciCheckB.js +6 -0
  125. package/dist/ciCheckB.js.map +1 -0
  126. package/dist/cli.d.ts +2 -0
  127. package/dist/cli.js +65 -0
  128. package/dist/cli.js.map +1 -0
  129. package/dist/commands/budget.d.ts +33 -0
  130. package/dist/commands/budget.js +108 -0
  131. package/dist/commands/budget.js.map +1 -0
  132. package/dist/commands/ci.d.ts +14 -0
  133. package/dist/commands/ci.js +157 -0
  134. package/dist/commands/ci.js.map +1 -0
  135. package/dist/commands/demo.d.ts +2 -0
  136. package/dist/commands/demo.js +163 -0
  137. package/dist/commands/demo.js.map +1 -0
  138. package/dist/commands/digest.d.ts +8 -0
  139. package/dist/commands/digest.js +189 -0
  140. package/dist/commands/digest.js.map +1 -0
  141. package/dist/commands/doctor.d.ts +2 -0
  142. package/dist/commands/doctor.js +98 -0
  143. package/dist/commands/doctor.js.map +1 -0
  144. package/dist/commands/drive.d.ts +3 -0
  145. package/dist/commands/drive.js +170 -0
  146. package/dist/commands/drive.js.map +1 -0
  147. package/dist/commands/gate.d.ts +2 -0
  148. package/dist/commands/gate.js +136 -0
  149. package/dist/commands/gate.js.map +1 -0
  150. package/dist/commands/honesty.d.ts +2 -0
  151. package/dist/commands/honesty.js +182 -0
  152. package/dist/commands/honesty.js.map +1 -0
  153. package/dist/commands/inspect.d.ts +2 -0
  154. package/dist/commands/inspect.js +244 -0
  155. package/dist/commands/inspect.js.map +1 -0
  156. package/dist/commands/install.d.ts +2 -0
  157. package/dist/commands/install.js +81 -0
  158. package/dist/commands/install.js.map +1 -0
  159. package/dist/commands/integrity.d.ts +2 -0
  160. package/dist/commands/integrity.js +74 -0
  161. package/dist/commands/integrity.js.map +1 -0
  162. package/dist/commands/memory.d.ts +6 -0
  163. package/dist/commands/memory.js +90 -0
  164. package/dist/commands/memory.js.map +1 -0
  165. package/dist/commands/pen.d.ts +17 -0
  166. package/dist/commands/pen.js +158 -0
  167. package/dist/commands/pen.js.map +1 -0
  168. package/dist/commands/prompt.d.ts +2 -0
  169. package/dist/commands/prompt.js +37 -0
  170. package/dist/commands/prompt.js.map +1 -0
  171. package/dist/commands/readyCheck.d.ts +21 -0
  172. package/dist/commands/readyCheck.js +68 -0
  173. package/dist/commands/readyCheck.js.map +1 -0
  174. package/dist/commands/report.d.ts +2 -0
  175. package/dist/commands/report.js +48 -0
  176. package/dist/commands/report.js.map +1 -0
  177. package/dist/commands/repro.d.ts +3 -0
  178. package/dist/commands/repro.js +61 -0
  179. package/dist/commands/repro.js.map +1 -0
  180. package/dist/commands/scan.d.ts +27 -0
  181. package/dist/commands/scan.js +348 -0
  182. package/dist/commands/scan.js.map +1 -0
  183. package/dist/commands/share.d.ts +2 -0
  184. package/dist/commands/share.js +163 -0
  185. package/dist/commands/share.js.map +1 -0
  186. package/dist/commands/trends.d.ts +2 -0
  187. package/dist/commands/trends.js +103 -0
  188. package/dist/commands/trends.js.map +1 -0
  189. package/dist/commands/try.d.ts +12 -0
  190. package/dist/commands/try.js +208 -0
  191. package/dist/commands/try.js.map +1 -0
  192. package/dist/commands/verify.d.ts +44 -0
  193. package/dist/commands/verify.js +381 -0
  194. package/dist/commands/verify.js.map +1 -0
  195. package/dist/commands/watch.d.ts +10 -0
  196. package/dist/commands/watch.js +70 -0
  197. package/dist/commands/watch.js.map +1 -0
  198. package/dist/evidence.d.ts +37 -0
  199. package/dist/evidence.js +61 -0
  200. package/dist/evidence.js.map +1 -0
  201. package/dist/graph/correlate.d.ts +7 -0
  202. package/dist/graph/correlate.js +246 -0
  203. package/dist/graph/correlate.js.map +1 -0
  204. package/dist/graph/integrity.d.ts +22 -0
  205. package/dist/graph/integrity.js +39 -0
  206. package/dist/graph/integrity.js.map +1 -0
  207. package/dist/installer/targets.d.ts +23 -0
  208. package/dist/installer/targets.js +162 -0
  209. package/dist/installer/targets.js.map +1 -0
  210. package/dist/memory/store.d.ts +33 -0
  211. package/dist/memory/store.js +131 -0
  212. package/dist/memory/store.js.map +1 -0
  213. package/dist/pen/dynamic.d.ts +36 -0
  214. package/dist/pen/dynamic.js +622 -0
  215. package/dist/pen/dynamic.js.map +1 -0
  216. package/dist/pen/fix.d.ts +35 -0
  217. package/dist/pen/fix.js +239 -0
  218. package/dist/pen/fix.js.map +1 -0
  219. package/dist/pen/proof.d.ts +46 -0
  220. package/dist/pen/proof.js +112 -0
  221. package/dist/pen/proof.js.map +1 -0
  222. package/dist/pen/report.d.ts +11 -0
  223. package/dist/pen/report.js +258 -0
  224. package/dist/pen/report.js.map +1 -0
  225. package/dist/pen/static.d.ts +17 -0
  226. package/dist/pen/static.js +565 -0
  227. package/dist/pen/static.js.map +1 -0
  228. package/dist/pen/store.d.ts +11 -0
  229. package/dist/pen/store.js +36 -0
  230. package/dist/pen/store.js.map +1 -0
  231. package/dist/pen/types.d.ts +112 -0
  232. package/dist/pen/types.js +53 -0
  233. package/dist/pen/types.js.map +1 -0
  234. package/dist/report/format.d.ts +126 -0
  235. package/dist/report/format.js +706 -0
  236. package/dist/report/format.js.map +1 -0
  237. package/dist/report/score.d.ts +47 -0
  238. package/dist/report/score.js +164 -0
  239. package/dist/report/score.js.map +1 -0
  240. package/dist/repro/framework.d.ts +26 -0
  241. package/dist/repro/framework.js +224 -0
  242. package/dist/repro/framework.js.map +1 -0
  243. package/dist/repro/generate.d.ts +14 -0
  244. package/dist/repro/generate.js +669 -0
  245. package/dist/repro/generate.js.map +1 -0
  246. package/dist/repro/ids.d.ts +32 -0
  247. package/dist/repro/ids.js +175 -0
  248. package/dist/repro/ids.js.map +1 -0
  249. package/dist/repro/index.d.ts +24 -0
  250. package/dist/repro/index.js +69 -0
  251. package/dist/repro/index.js.map +1 -0
  252. package/dist/repro/pen.d.ts +26 -0
  253. package/dist/repro/pen.js +321 -0
  254. package/dist/repro/pen.js.map +1 -0
  255. package/dist/repro/run.d.ts +18 -0
  256. package/dist/repro/run.js +36 -0
  257. package/dist/repro/run.js.map +1 -0
  258. package/dist/sandbox/proxy.d.ts +41 -0
  259. package/dist/sandbox/proxy.js +231 -0
  260. package/dist/sandbox/proxy.js.map +1 -0
  261. package/dist/sandbox/startCmd.d.ts +24 -0
  262. package/dist/sandbox/startCmd.js +71 -0
  263. package/dist/sandbox/startCmd.js.map +1 -0
  264. package/dist/ui/spinner.d.ts +18 -0
  265. package/dist/ui/spinner.js +26 -0
  266. package/dist/ui/spinner.js.map +1 -0
  267. package/dist/verify/metrics.d.ts +13 -0
  268. package/dist/verify/metrics.js +72 -0
  269. package/dist/verify/metrics.js.map +1 -0
  270. package/package.json +68 -0
  271. package/scripts/cheat-demo.cjs +102 -0
  272. package/templates/ledger/preload.cjs +331 -0
  273. package/templates/pen/preload.cjs +196 -0
  274. package/templates/pitstop.prompt.md +371 -0
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "pitstop-demo-api",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "description": "OpenPitStop's intentionally-broken demo API",
6
+ "scripts": {
7
+ "start": "node src/server.js",
8
+ "test": "jest"
9
+ },
10
+ "dependencies": {
11
+ "express": "^4.18.2",
12
+ "lodash": "4.17.15"
13
+ },
14
+ "devDependencies": {
15
+ "jest": "^29.7.0"
16
+ }
17
+ }
@@ -0,0 +1,5 @@
1
+ // Hardcoded credentials — gitleaks flags this for real when installed.
2
+ const API_KEY = "AKIA1234567890ABCDEFGH"; // fake AWS access key id
3
+ const DB_PASSWORD = "supersecretpassword123";
4
+
5
+ module.exports = { API_KEY, DB_PASSWORD };
@@ -0,0 +1,31 @@
1
+ // Fake in-memory data layer. In a real app this would open a DB connection.
2
+ const users = [
3
+ { id: 1, name: "alice", email: "alice@example.com", score: 70 },
4
+ { id: 2, name: "bob", email: "bob@example.com", score: 30 },
5
+ { id: 3, name: "carol", email: "carol@example.com", score: 10 },
6
+ ];
7
+
8
+ const posts = [
9
+ { id: 101, userId: 1, title: "Hello" },
10
+ { id: 102, userId: 1, title: "World" },
11
+ { id: 103, userId: 2, title: "Hi" },
12
+ ];
13
+
14
+ function query(sql, params) {
15
+ // Pretend this hits the database.
16
+ return [];
17
+ }
18
+
19
+ function getUsers() {
20
+ return users;
21
+ }
22
+
23
+ function getPostsByUser(userId) {
24
+ return posts.filter((p) => p.userId === userId);
25
+ }
26
+
27
+ function getConnection() {
28
+ return { query };
29
+ }
30
+
31
+ module.exports = { query, getUsers, getPostsByUser, getConnection };
@@ -0,0 +1,13 @@
1
+ const express = require("express");
2
+ const userController = require("./userController");
3
+
4
+ const app = express();
5
+
6
+ app.get("/users", userController.list);
7
+
8
+ if (require.main === module) {
9
+ const port = process.env.PORT || 3000;
10
+ app.listen(port, () => console.log(`pitstop-demo-api listening on ${port}`));
11
+ }
12
+
13
+ module.exports = app;
@@ -0,0 +1,22 @@
1
+ const service = require("./userService");
2
+ const db = require("./db");
3
+
4
+ function list(req, res) {
5
+ const users = service.listUsersWithPosts();
6
+ res.json(users);
7
+ }
8
+
9
+ function render(users) {
10
+ // --- DUPLICATED BLOCK (start) ---
11
+ return users.map((u) => {
12
+ const name = (u.name || "").toUpperCase();
13
+ const email = (u.email || "").toLowerCase();
14
+ const score = (u.score || 0) + 10;
15
+ const tier = score > 50 ? "gold" : score > 20 ? "silver" : "bronze";
16
+ const summary = `${name} <${email}> [${tier}]`;
17
+ return { id: u.id, summary, score };
18
+ });
19
+ // --- DUPLICATED BLOCK (end) ---
20
+ }
21
+
22
+ module.exports = { list, render };
@@ -0,0 +1,18 @@
1
+ const db = require("./db");
2
+ // Intentional layering violation: the repository reaches back up to the service.
3
+ const userService = require("./userService");
4
+
5
+ function getUsers() {
6
+ return db.getUsers();
7
+ }
8
+
9
+ function getPostsByUser(userId) {
10
+ return db.getPostsByUser(userId);
11
+ }
12
+
13
+ function getUserSummary(id) {
14
+ const u = db.getUsers().find((x) => x.id === id);
15
+ return userService.formatUser(u);
16
+ }
17
+
18
+ module.exports = { getUsers, getPostsByUser, getUserSummary };
@@ -0,0 +1,59 @@
1
+ const _ = require("lodash");
2
+ const repo = require("./userRepo");
3
+ // Intentional circular dependency: the service reaches into the controller.
4
+ const controller = require("./userController");
5
+ const config = require("./config");
6
+
7
+ // BUG: tier calculation is missing the "silver" band.
8
+ function calculateTier(score) {
9
+ if (score > 100) return "gold";
10
+ return "bronze";
11
+ }
12
+
13
+ // BUG: should uppercase the name but does nothing.
14
+ function normalizeName(name) {
15
+ return name;
16
+ }
17
+
18
+ function formatUser(u) {
19
+ return { id: u.id, name: u.name, email: u.email };
20
+ }
21
+
22
+ // N+1 query pattern: fetch all users, then one query per user for their posts.
23
+ // Spans userController -> userService -> userRepo (3 files).
24
+ function listUsersWithPosts() {
25
+ const users = repo.getUsers();
26
+ for (const u of users) {
27
+ u.posts = repo.getPostsByUser(u.id);
28
+ }
29
+ return users;
30
+ }
31
+
32
+ function summarize(users) {
33
+ // --- DUPLICATED BLOCK (start) ---
34
+ return users.map((u) => {
35
+ const name = (u.name || "").toUpperCase();
36
+ const email = (u.email || "").toLowerCase();
37
+ const score = (u.score || 0) + 10;
38
+ const tier = score > 50 ? "gold" : score > 20 ? "silver" : "bronze";
39
+ const summary = `${name} <${email}> [${tier}]`;
40
+ return { id: u.id, summary, score };
41
+ });
42
+ // --- DUPLICATED BLOCK (end) ---
43
+ }
44
+
45
+ function renderList() {
46
+ const users = listUsersWithPosts();
47
+ // The API key is "used" here only to make the config import reachable.
48
+ void config.API_KEY;
49
+ return controller.render(users);
50
+ }
51
+
52
+ module.exports = {
53
+ calculateTier,
54
+ normalizeName,
55
+ formatUser,
56
+ listUsersWithPosts,
57
+ summarize,
58
+ renderList,
59
+ };
@@ -0,0 +1,12 @@
1
+ const service = require("../src/userService");
2
+
3
+ describe("pitstop-demo-api", () => {
4
+ it("assigns the correct tier for a mid score", () => {
5
+ // score 30 -> +10 = 40 -> should be "silver"
6
+ expect(service.calculateTier(30)).toBe("silver");
7
+ });
8
+
9
+ it("uppercases the name", () => {
10
+ expect(service.normalizeName("bob")).toBe("BOB");
11
+ });
12
+ });
@@ -0,0 +1,27 @@
1
+ # pitstop-demo-fintech
2
+
3
+ > **This is OpenPitStop's intentionally-broken *fintech* demo repository.** It is the
4
+ > companion fixture for `pitstop scan --ledger`, whose job is to prove a **real
5
+ > double-charge** exists (not a simulated one).
6
+
7
+ ## What's broken (on purpose)
8
+
9
+ - `POST /api/orders/:id/charge` — takes `amount`/`currency` and an optional
10
+ `Idempotency-Key` header, forwards a real charge to the (mocked) `razorpay`
11
+ gateway… but **never dedupes on the idempotency key**. Fire the same key twice
12
+ and the gateway is charged twice.
13
+ - `POST /api/webhooks/razorpay` — on every `payment.captured` event it captures
14
+ the payment through the gateway with **no dedup**. Replay the same webhook and
15
+ the gateway is captured twice.
16
+
17
+ ## Safety
18
+
19
+ `pitstop scan --ledger` runs this app under a `nock` sandbox that intercepts
20
+ *every* outbound HTTP request before it leaves the process. The `razorpay`
21
+ requests land on a local mock and **never** reach a real payment gateway.
22
+
23
+ Run it (from the repo root):
24
+
25
+ ```
26
+ node dist/cli.js scan demo-repo-fintech --ledger
27
+ ```