Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
const runHint = async (t: ExecutionContext, hintTest: HintLocalTest) => {
try {
if (hintTest.before) {
await hintTest.before(t);
}
const hintConfig = createConfig(hintId, connector, configs);
const resources = resourceLoader.loadResources(hintConfig);
const engine = new Engine(hintConfig, resources);
// Can assume `getAsUri(hintTest.path)` is not `null` since these are controlled test inputs.
const target = getAsUri(hintTest.path)!;
const results = await engine.executeOn(target);
await engine.close();
if (hintTest.after) {
await hintTest.after(t);
}
const sources = new Map();
for (const result of results) {
if (!sources.has(result.resource)) {
sources.set(result.resource, await requestSource(result.resource, connector));
}
}
const requestSource = async (url: string, connector: string): Promise => {
try {
if (connector === 'local') {
return await readFileAsync(asPathString(getAsUri(url)!));
}
/*
* Allow us to use our self-signed cert for testing.
* https://github.com/request/request/issues/418#issuecomment-23058601
*/
return await requestAsync({
rejectUnauthorized: false,
strictSSL: false,
url
});
} catch (e) {
// Some tests deliberately use invalid URLs (e.g. `test:`).
return '';
}
};
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 = ({ element, resource, response }: FetchEnd) => {
const defaultValidators: Validator[] = [
validateNameAndValue,
validatePrefixes,
validateSecurityAttributes,
validateExpireDate,
validateMaxAgeAndExpires
];
// This check does not apply if URI starts with protocols others than http/https.
if (!isRegularProtocol(resource)) {
debug(`Check does not apply for URI: ${resource}`);
return;
}
const rawSetCookieHeaders: string | string[] = response.headers && response.headers['set-cookie'] || '';
if (!rawSetCookieHeaders) {
return;
}
/** The `chrome` connector concatenates all `set-cookie` headers to one string. */
const setCookieHeaders: string[] = Array.isArray(rawSetCookieHeaders) ? rawSetCookieHeaders : rawSetCookieHeaders.split(/\n|\r\n/);
const reportBatch = (errorMessages: ValidationMessages, codeLanguage: CodeLanguage, codeSnippet: string) => {
errorMessages.forEach(({ message, severity }) => {
private async fetchData(target: string, options?: IFetchOptions): Promise {
const content: NetworkData = await this.fetchContent(target, undefined, options);
const uri = getAsUri(target);
return {
element: null,
request: content.request,
resource: uri ? url.format(uri) : /* istanbul ignore next */ '',
response: content.response
};
}
const fileName = path.basename(resource);
/*
* In webpack documentation, this is the file name they
* always use: https://webpack.js.org/configuration/
*/
if (fileName !== 'webpack.config.js') {
return;
}
this.configFound = true;
await this.engine.emitAsync(`parse::start::webpack-config`, { resource });
try {
const config: webpack.Configuration = await import(asPathString(getAsUri(resource)!)); // `getAsUri(resource)` should not be null as the resource has already been fetched.
const version = await this.getLocallyInstalledWebpack();
if (!version) {
await this.engine.emitAsync('parse::error::webpack-config::not-install', {
error: new Error('webpack is not installed'),
resource
});
return;
}
await this.engine.emitAsync('parse::end::webpack-config', {
config,
resource,
version
public async fetchContent(target: string, headers?: object, options?: IFetchOptions): Promise {
/*
* target can have one of these forms:
* - /path/to/file
* - C:/path/to/file
* - file:///path/to/file
* - file:///C:/path/to/file
*
* That's why we need to parse it to an URL
* and then get the path string.
*/
const uri = getAsUri(target);
const filePath: string = uri ? asPathString(uri).replace('%20', ' ') : '';
const rawContent: Buffer = options && options.content ? Buffer.from(options.content) : await readFileAsBuffer(filePath);
const contentType = getContentTypeData(null as any, filePath, null, rawContent);
let content = '';
if (isTextMediaType(contentType.mediaType || '')) {
content = rawContent.toString(contentType.charset || undefined);
}
// Need to do some magic to create a fetch::end::*
return {
request: {} as any,
response: {
body: {
content,
rawContent,
export const finalConfig = (config: T, resource: string): T | IParsingError => {
if (!config.extends) {
return config;
}
const configIncludes = [];
// `resource` has already been loaded to provide `config` so `getAsUri` won't be null.
let configPath = asPathString(getAsUri(resource)!);
/*
* `configPath` will have the format c:/path or /path
* depending on what OS we are running sonar.
* In case that we are running on Windows, we need
* to normalize the path to c:\path before continue.
*/
configIncludes.push(path.normalize(configPath));
let finalConfigJSON: T = merge({}, config);
while (finalConfigJSON.extends) {
const lastPath = configPath;
const configDir = path.dirname(configPath);
configPath = path.resolve(configDir, finalConfigJSON.extends);
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;
}