Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
const checkForDisallowedCompressionMethods = async (resource: string, element: HTMLElement | null, response: Response) => {
// See: https://www.iana.org/assignments/http-parameters/http-parameters.xml.
const contentEncodingHeaderValue = normalizeHeaderValue(response.headers, 'content-encoding');
if (!contentEncodingHeaderValue) {
return;
}
const encodings = contentEncodingHeaderValue.split(',');
for (const encoding of encodings) {
if (!['gzip', 'br'].includes(encoding)) {
/*
* `x-gzip` is deprecated but usually user agents
* alias it to `gzip`, so if the content is actual
* `gzip`, don't trigger an error here as the gzip
* related check will show an error for the response
* not being served with `content-encoding: gzip`.
const validate = ({ resource, response }: FetchEnd) => {
if (response.statusCode !== 200) {
debug('Check does not apply to status code !== 200');
return;
}
// This check does not make sense for data URIs.
if (isDataURI(resource)) {
debug('Check does not apply for data URIs');
return;
}
const contentTypeHeaderValue = normalizeHeaderValue(response.headers, 'content-type');
const noSniff = normalizeHeaderValue(response.headers, 'x-content-type-options') === 'no-sniff';
const severity = noSniff ? Severity.error : Severity.warning;
const codeSnippet = `Content-Type: ${contentTypeHeaderValue}`;
const codeLanguage = 'http';
// Check if the `Content-Type` header was sent.
if (contentTypeHeaderValue === null) {
context.report(
resource,
getMessage('responseShouldIncludeContentType', context.language),
{ severity }
);
return;
}
const headers = requestConditions.request && requestConditions.request.headers;
/*
* Matching is done only based on headers, as for the time
* beeing there is no need to match based on other things.
*/
if (!headers) {
return 0;
}
let numberOfMatches = 0;
for (const [header, value] of Object.entries(headers)) {
// TODO: handle `string[]` in `req.headers`
const headerValue = normalizeHeaderValue(req.headers as any, header);
if ((headerValue !== normalizeString(value as string)) || (!headerValue && (value === null))) {
return 0;
}
numberOfMatches++;
}
return numberOfMatches;
}
if (!isCompressibleAccordingToMediaType(response.mediaType)) {
const safeRawResponse = asyncTry(response.body.rawResponse.bind(response.body));
const rawResponse: Buffer | null = await safeRawResponse();
if (!rawResponse) {
context.report(
resource,
getMessage('couldNotBeFetched', context.language),
{ element, severity: Severity.error }
);
return;
}
const contentEncodingHeaderValue = normalizeHeaderValue(response.headers, 'content-encoding');
// * Check if the resource is actually compressed.
if (await responseIsCompressed(rawResponse, contentEncodingHeaderValue)) {
context.report(
resource,
getMessage('shouldNotBeCompressed', context.language),
{ element, severity: Severity.warning }
);
}
// * Check if resource is sent with the `Content-Encoding` header.
if (contentEncodingHeaderValue) {
context.report(
resource,
getMessage('shouldNotIncludeContentEncoding', context.language),
{
const validate = (fetchEnd: FetchEnd, eventName: string) => {
const type: TargetType = eventName === 'fetch::end::html' ? 'html' : 'fetch';
const { resource } = fetchEnd;
// This check does not make sense for data URIs.
if (isDataURI(resource)) {
debug(`Check does not apply for data URIs`);
return;
}
const headers = fetchEnd.response.headers;
const { response: { mediaType } } = fetchEnd;
const cacheControlHeaderValue: string = normalizeHeaderValue(headers, 'cache-control', '')!; // won't return null since default value was provided
const parsedDirectives: ParsedDirectives = parseCacheControlHeader(cacheControlHeaderValue);
const validators = [
hasCacheControl,
hasInvalidDirectives,
hasNoneNonRecommendedDirectives,
validateDirectiveCombinations
];
if (type === 'html') {
validators.push(hasSmallCache);
} else if (type === 'fetch' && longCached.includes(mediaType)) {
// Check if there are custom revving patterns
let customRegex: RegExp[] | null = context.hintOptions && context.hintOptions.revvingPatterns || null;
if (customRegex) {
const getHeaderValues = (headers: HttpHeaders, headerName: string) => {
return (normalizeHeaderValue(headers, headerName) || '').split(',');
};
if (currentRedirectNumber > this._maxRedirects) {
return reject(`The number of redirects(${currentRedirectNumber}) exceeds the limit(${this._maxRedirects}).`);
}
try {
debug(`Redirect found for ${uriString}`);
const results = await getUri(newUri);
return resolve(results);
} catch (e) {
return reject(e);
}
}
const contentEncoding: string | null = normalizeHeaderValue(response.headers as HttpHeaders, 'content-encoding');
const rawBody: Buffer | null = await this.decompressResponse(contentEncoding, rawBodyResponse);
const contentTypeData = getContentTypeData(null, uri, response.headers as HttpHeaders, rawBody as Buffer);
const charset = contentTypeData.charset || '';
const mediaType = contentTypeData.mediaType || '';
const hops: string[] = this._redirects.calculate(uriString);
const body: string | null = rawBody && iconv.encodingExists(charset) ? iconv.decode(rawBody, charset) : null;
const networkData: NetworkData = {
request: {
headers: response.request.headers,
url: hops[0] || uriString
},
response: {
body: {
content: body as string,
rawContent: rawBody as Buffer,
* `server` is not specified by the user as a disallowed
* header or a header to be ignored, check if it provides
* more information than it should.
*
* The `Server` header is treated differently than the
* other ones because it cannot always be remove. In some
* cases such as Apache the best that the user can do is
* limit it's value to the name of the server (i.e. apache).
*
* See also:
*
* * https://bz.apache.org/bugzilla/show_bug.cgi?id=40026
* * https://httpd.apache.org/docs/current/mod/core.html#servertokens
*/
const serverHeaderValue = normalizeHeaderValue(response.headers, 'server');
const codeLanguage = 'http';
if (!disallowedHeaders.includes('server') &&
!toLowerCaseArray(ignoreHeaders).includes('server') &&
serverHeaderValue &&
serverHeaderContainsTooMuchInformation(serverHeaderValue)
) {
const message = getMessage('headerValueShouldOnlyContain', context.language, response.headers.server);
context.report(
resource,
message,
{
codeLanguage,
codeSnippet: `Server: ${serverHeaderValue}`,
severity: Severity.warning
const codeSnippet = headers.reduce((total, header) => {
return `${total}${total ? '\n' : ''}${header}: ${normalizeHeaderValue(response.headers, header)}`;
}, '');