@clear-capabilities/agentic-security-scanner 0.186.2 → 0.188.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.
- package/CHANGELOG.md +20 -0
- package/dist/1602.index.js +275 -19
- package/dist/{4d06c8944ae121d7085c.json → 92f78fd3e2dbe30fb58d.json} +5 -5
- package/dist/9560.index.js +61 -4
- package/dist/agentic-security.mjs +2 -2
- package/dist/agentic-security.mjs.sha256 +1 -1
- package/package.json +5 -5
- package/src/capabilities/decide.js +7 -1
- package/src/dataflow/CLAUDE.md +15 -0
- package/src/dataflow/catalog-haskell.js +7 -1
- package/src/dataflow/catalog.js +14 -0
- package/src/dataflow/engine.js +147 -10
- package/src/dataflow/privacy-catalog-haskell.js +2 -1
- package/src/engine.js +11 -3
- package/src/language/CLAUDE.md +26 -0
- package/src/language/compliance-map.js +6 -0
- package/src/language/context.js +20 -0
- package/src/language/haskell-comments.js +65 -0
- package/src/language/haskell-disclosure.js +16 -4
- package/src/language/haskell-findings.js +2 -1
- package/src/language/haskell-fix.js +118 -2
- package/src/language/haskell-guards.js +132 -5
- package/src/language/haskell-ir.js +228 -13
- package/src/language/haskell-models.js +108 -8
- package/src/language/haskell-security-rules.js +223 -41
- package/src/language/haskell-syntax.js +10 -1
- package/src/language/haskell-trust.js +268 -0
- package/src/language/haskell-web.js +46 -9
- package/src/language/support-registry.js +3 -2
- package/src/mcp/tools.js +54 -3
- package/src/posture/attack-taxonomy.js +10 -0
- package/src/posture/entrypoint-inventory.js +6 -2
- package/src/posture/proof-fabric/generate-haskell.js +266 -17
- package/src/posture/proof-fabric/generate.js +10 -3
- package/src/posture/proof-fabric/oracles.js +21 -0
- package/src/posture/stable-id.js +2 -1
- package/src/report/index.js +3 -0
- package/src/sast/cloud-iam.js +3 -1
- package/dist/2066.index.js +0 -851
|
@@ -71,6 +71,13 @@ export const HS_PACKAGES = Object.freeze({
|
|
|
71
71
|
'clientsession': { modules: ['Web.ClientSession'], tested: [] },
|
|
72
72
|
connection: { modules: ['Network.Connection'], tested: [] },
|
|
73
73
|
HsOpenSSL: { modules: ['OpenSSL.Session'], tested: [] },
|
|
74
|
+
'wai-extra': { modules: ['Network.Wai.Parse', 'Network.Wai.Conduit'], tested: [] },
|
|
75
|
+
'scotty-cookie': { modules: ['Web.Scotty.Cookie'], tested: [] },
|
|
76
|
+
ihp: { modules: ['IHP.ControllerPrelude', 'IHP.Controller.Param'], tested: [] },
|
|
77
|
+
'http-types': { modules: ['Network.HTTP.Types', 'Network.HTTP.Types.Header'], tested: [] },
|
|
78
|
+
'conduit-extra': { modules: ['Data.Conduit.Binary', 'Data.Conduit.Combinators'], tested: [] },
|
|
79
|
+
'uri-parsing': { modules: ['Text.URI'], tested: [] },
|
|
80
|
+
'snap-fileserve': { modules: ['Snap.Util.FileServe'], tested: [] },
|
|
74
81
|
});
|
|
75
82
|
|
|
76
83
|
// ── sources ─────────────────────────────────────────────────────────────────
|
|
@@ -79,10 +86,16 @@ const SRC = [];
|
|
|
79
86
|
const src = (module, names, provenance, label, extra = {}) => { for (const e of E(module, names)) SRC.push({ ...e, provenance, label: `${label}${names.length > 1 ? '' : ''}`, package: extra.package, framework: extra.framework || null }); };
|
|
80
87
|
|
|
81
88
|
src('Prelude', ['getLine', 'getContents', 'readLn', 'interact'], 'stdin', 'standard input', { package: 'base' });
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
src('
|
|
85
|
-
src('
|
|
89
|
+
// `getLine` and `getContents` read standard input. `hGetLine`/`hGetContents`/`hGetChar` read WHATEVER handle they are given (a file the program opened,
|
|
90
|
+
// a child process's pipe, a socket, or stdin), so they are modelled as a read through a handle, not as standard input.
|
|
91
|
+
src('System.IO', ['getLine', 'getContents'], 'stdin', 'handle input', { package: 'base' });
|
|
92
|
+
src('System.IO', ['hGetLine', 'hGetContents', 'hGetChar'], 'file-read', 'handle input', { package: 'base' });
|
|
93
|
+
src('Data.Text.IO', ['getLine', 'getContents', 'interact'], 'stdin', 'text input', { package: 'text' });
|
|
94
|
+
src('Data.Text.IO', ['hGetLine', 'hGetContents'], 'file-read', 'text input', { package: 'text' });
|
|
95
|
+
src('Data.ByteString', ['getLine', 'getContents'], 'stdin', 'bytes input', { package: 'bytestring' });
|
|
96
|
+
src('Data.ByteString', ['hGetLine', 'hGetContents'], 'file-read', 'bytes input', { package: 'bytestring' });
|
|
97
|
+
src('Data.ByteString.Char8', ['getLine', 'getContents'], 'stdin', 'bytes input', { package: 'bytestring' });
|
|
98
|
+
src('Data.ByteString.Char8', ['hGetLine', 'hGetContents'], 'file-read', 'bytes input', { package: 'bytestring' });
|
|
86
99
|
src('System.Environment', ['getArgs'], 'cli', 'command-line argument', { package: 'base' });
|
|
87
100
|
src('System.Environment', ['getEnv', 'lookupEnv', 'getEnvironment'], 'env', 'environment variable', { package: 'base' });
|
|
88
101
|
src('Prelude', ['readFile'], 'file-read', 'file content', { package: 'base' });
|
|
@@ -131,6 +144,52 @@ src('Yesod', ['getRequest', 'rawRequestBody', 'runRequestBody', 'lookupFile', 'l
|
|
|
131
144
|
// Scotty: the underlying WAI request
|
|
132
145
|
src('Web.Scotty', ['request'], 'http-body', 'scotty WAI request', { package: 'scotty', framework: 'scotty' });
|
|
133
146
|
src('Web.Scotty.Trans', ['request'], 'http-body', 'scotty WAI request', { package: 'scotty', framework: 'scotty' });
|
|
147
|
+
// The request accessors a handler really uses, beyond the first few: the Maybe/Either forms of the same parameter reads (scotty 0.20+),
|
|
148
|
+
// the raw body reader, cookies, and the JSON body helpers of yesod. Each reads a value the client controls.
|
|
149
|
+
for (const mod of ['Web.Scotty', 'Web.Scotty.Trans']) {
|
|
150
|
+
src(mod, ['queryParamMaybe', 'pathParamMaybe', 'formParamMaybe', 'queryParamEither', 'formParamEither', 'paramsEither'], 'url-param', 'scotty request parameter', { package: 'scotty', framework: 'scotty' });
|
|
151
|
+
src(mod, ['bodyReader', 'bodyRaw'], 'http-body', 'scotty request body', { package: 'scotty', framework: 'scotty' });
|
|
152
|
+
}
|
|
153
|
+
src('Web.Scotty.Cookie', ['getCookie', 'getCookies'], 'cookie', 'scotty request cookie', { package: 'scotty-cookie', framework: 'scotty' });
|
|
154
|
+
// IHP: a controller action reads the request with `param @Text "name"` (a pure function over the implicit request): the value is whatever the client sent.
|
|
155
|
+
for (const mod of ['IHP.ControllerPrelude', 'IHP.Controller.Param']) {
|
|
156
|
+
src(mod, ['param', 'paramText', 'paramOrNothing', 'paramOrDefault', 'paramList'], 'url-param', 'IHP request parameter', { package: 'ihp', framework: 'ihp' });
|
|
157
|
+
}
|
|
158
|
+
for (const mod of ['Yesod.Core', 'Yesod']) {
|
|
159
|
+
src(mod, ['parseJsonBody', 'requireJsonBody', 'parseCheckJsonBody', 'requireCheckJsonBody', 'lookupCookies', 'lookupHeaders'], 'http-body', 'yesod request body', { package: 'yesod', framework: 'yesod' });
|
|
160
|
+
src(mod, ['lookupBasicAuth'], 'header', 'yesod request header', { package: 'yesod', framework: 'yesod' });
|
|
161
|
+
}
|
|
162
|
+
src('Yesod.Core.Json', ['parseJsonBody', 'requireJsonBody', 'parseCheckJsonBody', 'requireCheckJsonBody'], 'http-body', 'yesod request body', { package: 'yesod', framework: 'yesod' });
|
|
163
|
+
// WAI: the multipart/form body parsers and the conduit request body, and the request's host and cookie headers
|
|
164
|
+
src('Network.Wai.Parse', ['parseRequestBody', 'parseRequestBodyEx'], 'http-body', 'WAI parsed request body', { package: 'wai-extra', framework: 'wai' });
|
|
165
|
+
src('Network.Wai.Conduit', ['sourceRequestBody'], 'http-body', 'WAI request body stream', { package: 'wai-extra', framework: 'wai' });
|
|
166
|
+
|
|
167
|
+
// A text parameter of an exported function that returns a web-framework HANDLER value (a Scotty action, a Yesod handler or widget, a Servant handler,
|
|
168
|
+
// a WAI application) receives what the framework took from the request: a route piece, a query value, a body field. That is a request source, so it
|
|
169
|
+
// is labelled as one. Every other exported function's text parameter stays the weaker `hs:caller-controlled` source (the caller of a library
|
|
170
|
+
// function is not known to be a client). The module must import the framework AND the function's declared result must be its handler type; a
|
|
171
|
+
// helper in a framework module that returns plain text is not a handler.
|
|
172
|
+
export const HS_HANDLER_PARAM_SOURCES = Object.freeze({
|
|
173
|
+
scotty: { decorator: 'hs:handler-param:scotty', framework: 'scotty', modules: ['Web.Scotty', 'Web.Scotty.Trans'], result: /\b(?:ActionM|ActionT)\b/, provenance: 'url-param', label: 'route, query or body value handed to a Scotty action (request input)' },
|
|
174
|
+
yesod: { decorator: 'hs:handler-param:yesod', framework: 'yesod', modules: ['Yesod', 'Yesod.Core', 'Yesod.Auth'], result: /\b(?:Handler|HandlerFor|HandlerT|Widget|WidgetFor|WidgetT)\b/, provenance: 'url-param', label: 'route piece or request value handed to a Yesod handler (request input)' },
|
|
175
|
+
servant: { decorator: 'hs:handler-param:servant', framework: 'servant', modules: ['Servant', 'Servant.API', 'Servant.Server', 'Servant.Auth', 'Servant.Auth.Server'], result: /\b(?:Handler|ServerT|AppM)\b/, provenance: 'url-param', label: 'capture, query or body value handed to a Servant handler (request input)' },
|
|
176
|
+
wai: { decorator: 'hs:handler-param:wai', framework: 'wai', modules: ['Network.Wai', 'Network.Wai.Handler.Warp'], result: /\b(?:ResponseReceived|Application|Middleware)\b/, provenance: 'url-param', label: 'request value handed to a WAI application (request input)' },
|
|
177
|
+
});
|
|
178
|
+
/** What a parameter-annotation source says about itself: the label an evidence chain shows and, for a request value, its provenance. */
|
|
179
|
+
export function paramSourceInfo(decorator) {
|
|
180
|
+
for (const d of Object.values(HS_HANDLER_PARAM_SOURCES)) if (d.decorator === decorator) return { label: d.label, provenance: d.provenance };
|
|
181
|
+
if (decorator === 'hs:caller-controlled') return { label: 'text parameter of an exported function (caller-controlled)', provenance: null };
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
/** The framework whose handler type a function with this signature returns, among the frameworks the module imports; null for a plain library function. */
|
|
185
|
+
export function handlerFrameworkOf(importedModules, resultText) {
|
|
186
|
+
if (!resultText) return null;
|
|
187
|
+
const mods = new Set(importedModules || []);
|
|
188
|
+
for (const def of Object.values(HS_HANDLER_PARAM_SOURCES)) {
|
|
189
|
+
if (def.modules.some((m) => mods.has(m)) && def.result.test(resultText)) return def;
|
|
190
|
+
}
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
134
193
|
|
|
135
194
|
// ── sinks ───────────────────────────────────────────────────────────────────
|
|
136
195
|
// family: the taint family the existing engine already uses (cmd | sql | path | url | xss)
|
|
@@ -169,9 +228,12 @@ sink('Database.Persist.Sql', ['rawSql', 'rawExecute', 'rawQuery'], { ...SQL, arg
|
|
|
169
228
|
|
|
170
229
|
// CWE-918. The URL (or request spec built from it) is the sink.
|
|
171
230
|
const SSRF = { family: 'url', cwe: 'CWE-918', severity: 'high', argIndex: 0, vuln: 'Server-Side Request Forgery', remediation: 'Parse the URL, require an allow-listed scheme and host, and reject private or link-local addresses after DNS resolution.' };
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
sink('Network.HTTP.
|
|
231
|
+
// The SEND is the sink, not the parse: `parseRequest url` only builds a Request value, and the host check a defence needs (`host req \`elem\` allowed`)
|
|
232
|
+
// can only be written AFTER that parse. A sink on the parse would sit before every such check and report every guarded flow.
|
|
233
|
+
sink('Network.HTTP.Simple', ['httpBS', 'httpLBS', 'httpJSON', 'httpNoBody', 'httpSink'], { ...SSRF, package: 'http-conduit' });
|
|
234
|
+
sink('Network.HTTP.Conduit', ['simpleHttp'], { ...SSRF, package: 'http-conduit' });
|
|
235
|
+
// http-conduit re-exports the http-client senders under its own module names, and conduit-flavoured modules add their own
|
|
236
|
+
for (const mod of ['Network.HTTP.Conduit', 'Network.HTTP.Client.Conduit']) sink(mod, ['httpLbs', 'httpNoBody', 'http', 'withResponse', 'responseOpen'], { ...SSRF, argIndex: 0, package: 'http-conduit' });
|
|
175
237
|
sink('Network.HTTP.Client', ['httpLbs', 'httpNoBody', 'withResponse', 'responseOpen'], { ...SSRF, argIndex: 0, package: 'http-client' });
|
|
176
238
|
// wreq: where the URL sits depends on the function. `get url`, but `getWith opts url` (the first argument is the Options, not the target),
|
|
177
239
|
// `customMethod method url`, `customMethodWith method opts url`; the Session forms take the session before the URL.
|
|
@@ -197,6 +259,10 @@ sink('Text.Blaze.Html5', ['preEscapedToHtml'], { ...XSS, package: 'blaze-html' }
|
|
|
197
259
|
sink('Lucid', ['toHtmlRaw'], { ...XSS, package: 'lucid' });
|
|
198
260
|
sink('Lucid.Base', ['toHtmlRaw'], { ...XSS, package: 'lucid' });
|
|
199
261
|
sink('Text.Hamlet', ['preEscapedToMarkup'], { ...XSS, package: 'shakespeare' });
|
|
262
|
+
// `Yesod` and `Yesod.Core` re-export the blaze pre-escaped constructors, so the same call resolves to those modules
|
|
263
|
+
for (const mod of ['Yesod', 'Yesod.Core', 'Yesod.Core.Widget', 'Text.Blaze', 'Text.Blaze.Html', 'Text.Blaze.Html5', 'Text.Blaze.Internal']) {
|
|
264
|
+
sink(mod, ['preEscapedToMarkup', 'preEscapedToHtml'], { ...XSS, package: mod.startsWith('Yesod') ? 'yesod' : 'blaze-html', ...(mod.startsWith('Yesod') ? { framework: 'yesod' } : {}) });
|
|
265
|
+
}
|
|
200
266
|
sink('Web.Scotty', ['html'], { ...XSS, package: 'scotty', framework: 'scotty', vuln: 'Cross-Site Scripting (HTML response from text)' });
|
|
201
267
|
sink('Web.Scotty.Trans', ['html'], { ...XSS, package: 'scotty', framework: 'scotty', vuln: 'Cross-Site Scripting (HTML response from text)' });
|
|
202
268
|
|
|
@@ -232,6 +298,10 @@ for (const mod of ['Database.Persist.Postgresql', 'Database.Persist.Sqlite', 'Da
|
|
|
232
298
|
|
|
233
299
|
// CWE-918. Req builds a URL from typed pieces, so the HOST is the attacker-steered part; HTTP's request constructors take the URL text.
|
|
234
300
|
sink('Network.HTTP.Req', ['https', 'http'], { ...SSRF, argIndex: 0, package: 'req', vuln: 'Server-Side Request Forgery (request host)' });
|
|
301
|
+
// `useURI` turns a parsed URI (often one the caller supplied) into the host-and-path pair `req` sends to. The tainted value is the whole URI, which
|
|
302
|
+
// names the host: that is the point the request target is chosen. (`req` itself is not a sink: its URL argument is usually built from a fixed host
|
|
303
|
+
// and tainted path segments, which `https "host" /: segment` keeps on that host.)
|
|
304
|
+
sink('Network.HTTP.Req', ['useURI'], { ...SSRF, argIndex: 0, package: 'req', vuln: 'Server-Side Request Forgery (request target from a parsed URI)' });
|
|
235
305
|
sink('Network.HTTP', ['getRequest', 'postRequest', 'headRequest', 'simpleHTTP'], { ...SSRF, argIndex: 0, package: 'HTTP' });
|
|
236
306
|
|
|
237
307
|
// CWE-601. Redirecting to a location taken from the request sends the user to a site the attacker names.
|
|
@@ -252,6 +322,17 @@ sink('Data.ByteString.Lazy.Char8', ['readFile', 'writeFile', 'appendFile'], { fa
|
|
|
252
322
|
sink('Data.Text.Lazy.IO', ['readFile', 'writeFile', 'appendFile'], { family: 'path', cwe: 'CWE-22', severity: 'high', argIndex: 0, package: 'text', vuln: 'Path Traversal', remediation: 'Confirm the canonical path stays under an allowed directory before opening it.' });
|
|
253
323
|
sink('System.Posix.Files', ['removeLink', 'createSymbolicLink', 'setFileMode', 'setOwnerAndGroup', 'readSymbolicLink'], { family: 'path', cwe: 'CWE-22', severity: 'high', argIndex: 0, package: 'unix', vuln: 'Path Traversal (file operation)', remediation: 'Confirm the canonical path stays under an allowed directory before the operation.' });
|
|
254
324
|
sink('System.Posix.Files', ['rename'], { family: 'path', cwe: 'CWE-22', severity: 'high', argIndex: 'all', package: 'unix', vuln: 'Path Traversal (rename)', remediation: 'Confirm both canonical paths stay under an allowed directory.' });
|
|
325
|
+
// Serving a file named by the request: the web frameworks' own file responses take a FilePath. (WAI `responseFile status headers path part`
|
|
326
|
+
// has the path third; Yesod's `sendFile contentType path` second.)
|
|
327
|
+
const PATH_RESPONSE = { family: 'path', cwe: 'CWE-22', severity: 'high', argIndex: 0, vuln: 'Path Traversal (file served from a request-chosen path)', remediation: 'Serve files only from a fixed directory: reject any name containing a path separator or `..` (`takeFileName p == p`), or look the file up in an allow-list.' };
|
|
328
|
+
sink('Web.Scotty', ['file'], { ...PATH_RESPONSE, package: 'scotty', framework: 'scotty' });
|
|
329
|
+
sink('Web.Scotty.Trans', ['file'], { ...PATH_RESPONSE, package: 'scotty', framework: 'scotty' });
|
|
330
|
+
sink('Yesod.Core', ['sendFile', 'sendFilePart'], { ...PATH_RESPONSE, argIndex: 1, package: 'yesod', framework: 'yesod' });
|
|
331
|
+
sink('Yesod', ['sendFile', 'sendFilePart'], { ...PATH_RESPONSE, argIndex: 1, package: 'yesod', framework: 'yesod' });
|
|
332
|
+
sink('Network.Wai', ['responseFile'], { ...PATH_RESPONSE, argIndex: 2, package: 'wai', framework: 'wai' });
|
|
333
|
+
sink('Snap.Core', ['sendFile'], { ...PATH_RESPONSE, package: 'snap', framework: 'snap' });
|
|
334
|
+
sink('Snap.Util.FileServe', ['serveFile'], { ...PATH_RESPONSE, package: 'snap-fileserve', framework: 'snap' });
|
|
335
|
+
sink('Snap.Util.FileServe', ['serveFileAs'], { ...PATH_RESPONSE, argIndex: 1, package: 'snap-fileserve', framework: 'snap' });
|
|
255
336
|
|
|
256
337
|
// ── sanitizers (context-specific; `appliesTo` is the family each one actually neutralises) ──
|
|
257
338
|
const SAN = [];
|
|
@@ -287,6 +368,9 @@ export const HS_LOG_SINKS = Object.freeze([
|
|
|
287
368
|
...E('System.IO', ['appendFile']).map((e) => ({ ...e, argIndex: 1, channel: 'file' })),
|
|
288
369
|
...E('Debug.Trace', ['trace', 'traceShow', 'traceM', 'traceShowM', 'traceShowId', 'traceId']).map((e) => ({ ...e, argIndex: 0, channel: 'trace' })),
|
|
289
370
|
...E('Control.Monad.Logger', ['logDebugN', 'logInfoN', 'logWarnN', 'logErrorN', 'logOtherN']).map((e) => ({ ...e, argIndex: 0, channel: 'logger' })),
|
|
371
|
+
// printf is variadic: the format string is argument 0 and every later argument is a value interpolated into the message
|
|
372
|
+
...E('Text.Printf', ['printf']).map((e) => ({ ...e, argIndex: 0, argFrom: 0, channel: 'stdout' })),
|
|
373
|
+
...E('Text.Printf', ['hPrintf']).map((e) => ({ ...e, argIndex: 1, argFrom: 1, channel: 'handle' })),
|
|
290
374
|
...E('Katip', ['logFM', 'logTM', 'logItem']).map((e) => ({ ...e, argIndex: 1, channel: 'logger' })),
|
|
291
375
|
...E('System.Log.Logger', ['debugM', 'infoM', 'noticeM', 'warningM', 'errorM', 'criticalM']).map((e) => ({ ...e, argIndex: 1, channel: 'logger' })),
|
|
292
376
|
]);
|
|
@@ -301,7 +385,7 @@ export const HS_RULE_APIS = Object.freeze([
|
|
|
301
385
|
...E('Crypto.Cipher.Types', ['makeIV', 'ecbEncrypt', 'ecbDecrypt', 'nullIV', 'cbcEncrypt', 'cbcDecrypt']),
|
|
302
386
|
...E('Crypto.Cipher.ChaChaPoly1305', ['nonce12', 'nonce8']),
|
|
303
387
|
...E('Crypto.KDF.PBKDF2', ['generate', 'fastPBKDF2_SHA1', 'fastPBKDF2_SHA256', 'fastPBKDF2_SHA512']),
|
|
304
|
-
...E('System.Random', ['randomRIO', 'randomIO', 'newStdGen', 'getStdGen', 'mkStdGen', 'randomR', 'random', 'randoms', 'randomRs']),
|
|
388
|
+
...E('System.Random', ['randomRIO', 'randomIO', 'newStdGen', 'getStdGen', 'mkStdGen', 'randomR', 'random', 'randoms', 'randomRs', 'getStdRandom', 'uniformR', 'uniform', 'initStdGen']),
|
|
305
389
|
...E('Crypto.Random', ['getRandomBytes']), ...E('System.Entropy', ['getEntropy']),
|
|
306
390
|
...E('Network.Wai', ['strictRequestBody', 'lazyRequestBody']),
|
|
307
391
|
...E('Data.Time.Clock.POSIX', ['getPOSIXTime']), ...E('Data.Time.Clock', ['getCurrentTime']), ...E('System.CPUTime', ['getCPUTime']),
|
|
@@ -311,6 +395,22 @@ export const HS_RULE_APIS = Object.freeze([
|
|
|
311
395
|
...E('Data.Text.IO', ['getContents', 'hGetContents']), ...E('Data.Text.Lazy.IO', ['getContents', 'hGetContents']),
|
|
312
396
|
...E('Data.Text', ['replicate', 'take']), ...E('Data.Vector', ['replicate']),
|
|
313
397
|
...E('Web.Cookie', ['defaultSetCookie']),
|
|
398
|
+
// session cookies set without the flags: scotty-cookie's helper builds a cookie with no Secure and no HttpOnly; a Set-Cookie header written by hand
|
|
399
|
+
...E('Web.Scotty.Cookie', ['setSimpleCookie', 'makeSimpleCookie']),
|
|
400
|
+
...E('Network.HTTP.Types.Header', ['hSetCookie']), ...E('Network.HTTP.Types', ['hSetCookie']),
|
|
401
|
+
...E('Servant.Auth.Server', ['defaultCookieSettings']),
|
|
402
|
+
// unbounded reads: a request body drained into memory, a socket read in a loop
|
|
403
|
+
...E('Network.Wai.Conduit', ['sourceRequestBody']), ...E('Network.Wai', ['getRequestBodyChunk', 'requestBody', 'requestBodyLength']),
|
|
404
|
+
...E('Data.Conduit.Binary', ['sinkLbs', 'take', 'isolate']), ...E('Data.Conduit.Combinators', ['sinkLazy', 'sinkLazyBuilder', 'take', 'takeE']),
|
|
405
|
+
...E('Network.Socket.ByteString', ['recv', 'recvFrom']), ...E('Network.Socket.ByteString.Lazy', ['recv', 'getContents']), ...E('System.IO', ['hGetSome', 'hGetLine']),
|
|
406
|
+
// partial functions that raise on an empty or short input, and the Map lookup that raises on a missing key
|
|
407
|
+
...E('Prelude', ['head', 'tail', 'last', 'init', 'maximum', 'minimum', 'foldr1', 'foldl1', 'read', 'toEnum', 'succ', 'pred', 'cycle']),
|
|
408
|
+
...E('Data.List', ['head', 'tail', 'last', 'init', 'maximum', 'minimum', 'foldr1', 'foldl1', 'maximumBy', 'minimumBy', '!!', 'genericIndex']),
|
|
409
|
+
...E('Data.Foldable', ['maximum', 'minimum', 'foldr1', 'foldl1', 'maximumBy', 'minimumBy']),
|
|
410
|
+
...E('Data.Map', ['!', 'findMin', 'findMax', 'deleteFindMin', 'elemAt']), ...E('Data.Map.Strict', ['!', 'findMin', 'findMax', 'deleteFindMin', 'elemAt']),
|
|
411
|
+
...E('Data.HashMap.Strict', ['!']), ...E('Data.IntMap', ['!']), ...E('Data.IntMap.Strict', ['!']), ...E('Data.Set', ['findMin', 'findMax', 'elemAt']),
|
|
412
|
+
...E('Data.Text', ['head', 'last', 'tail', 'init', 'maximum', 'minimum', 'index']),
|
|
413
|
+
...E('Data.Maybe', ['fromJust']),
|
|
314
414
|
...E('Web.JWT', ['hmacSecret', 'secret']), ...E('Servant.Auth.Server', ['fromSecret']), ...E('Web.ClientSession', ['initKey']),
|
|
315
415
|
...E('Network.HTTP.Client.TLS', ['mkManagerSettings']), ...E('OpenSSL.Session', ['contextSetVerificationMode']),
|
|
316
416
|
...E('Text.XML.HXT.Core', ['withSubstDTDEntities']),
|