Skip to content

Commit

Permalink
Provides warnings on un-sanitized request variables
Browse files Browse the repository at this point in the history
  • Loading branch information
JohnathonKoster committed Jul 17, 2022
1 parent ce75952 commit d385c90
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 1 deletion.
2 changes: 2 additions & 0 deletions server/src/diagnostics/handlers/coreHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ import RelateTagHandler from './relateHandler';
import ShorthandModifierHandler from './shorthandModifierHandler';
import StatamicVersionHandler from './statamicVersionHandler';
import TagsThatErrorHandler from './tagsThatErrorHandler';
import UrlInputHandler from './urlInputHandler';

const CoreHandlers: IDiagnosticsHandler[] = [
DataDumpHandler,
UrlInputHandler,
MixedModifierHandler,
ModifierRuntimeTypeHandler,
DoubleColonHandler,
Expand Down
58 changes: 58 additions & 0 deletions server/src/diagnostics/handlers/urlInputHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { AntlersError, ErrrorLevel } from '../../runtime/errors/antlersError';
import { AntlersErrorCodes } from '../../runtime/errors/antlersErrorCodes';
import { AntlersNode } from '../../runtime/nodes/abstractNode';
import { intersect } from '../../runtime/utilities/arrayHelpers';
import { IDiagnosticsHandler } from '../diagnosticsHandler';
import ModifierManager from '../../antlers/modifierManager';

const UrlInputHandler: IDiagnosticsHandler = {
checkNode(node: AntlersNode) {
const tagName = node.getTagName().toLowerCase(),
errors: AntlersError[] = [];
if (tagName == 'get' || tagName == 'post') {
const overlap = intersect(ModifierManager.instance?.getModifierNames() ?? [], node.modifiers.modifierNames);

// Return early if the developer is using custom modifiers. These may sanitize.
if (overlap.length == 0 && node.modifiers.modifierNames.length > 0 &&
(node.modifiers.modifierNames.length == 1 && ModifierManager?.instance?.hasMacro(node.modifiers.modifierNames[0])) == false) {
return errors;
}

let foundSanitizeInMacro = false;

for (let i = 0; i < node.modifiers.modifierNames.length; i++) {
const name = node.modifiers.modifierNames[i];

if (ModifierManager.instance?.hasMacro(name)) {
const macro = ModifierManager.instance?.getMacro(name);

if (macro != null) {
for (let j = 0; j < macro.modifiers.length; j++) {
const macroModifier = macro.modifiers[j];

if (macroModifier.name == 'sanitize') {
foundSanitizeInMacro = true;
break;
}
}
}
}
}

if (foundSanitizeInMacro == true) { return errors; }

if (node.modifiers.modifierNames.includes('sanitize') == false) {
errors.push(AntlersError.makeSyntaxError(
AntlersErrorCodes.LINT_URL_VARIABLE_WITHOUT_SANITIZE,
node,
'Request variables can be controlled by the end user, and should be sanitized',
ErrrorLevel.Warning
));
}
}

return errors;
}
}

export default UrlInputHandler;
1 change: 1 addition & 0 deletions server/src/runtime/errors/antlersErrorCodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,4 +157,5 @@ export class AntlersErrorCodes {
static readonly LINT_INTERLEAVED_TAG_PAIRS = 'ANTLR_516';
static readonly LINT_MISSING_REQUIRED_PARAMETER = 'ANTLR_517';
static readonly LINT_POSSIBLE_PARTIAL_RECURSION = 'ANTLR_518';
static readonly LINT_URL_VARIABLE_WITHOUT_SANITIZE = 'ANTLR_519';
}
12 changes: 11 additions & 1 deletion server/src/runtime/parser/languageParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export class LanguageParser {
private pathParser: PathParser = new PathParser();
protected tokens: AbstractNode[] = [];

private createdVariables: VariableNode[] = [];
private createdModifierChains: ModifierChainNode[] = [];
private createdLanguageOperators: LanguageOperatorConstruct[] = [];
private createdArrays: ArrayNode[] = [];
Expand Down Expand Up @@ -62,6 +63,10 @@ export class LanguageParser {
return this.createdArrays;
}

public getCreatedVariables(): VariableNode[] {
return this.createdVariables;
}

public getRuntimeAssignments(): StaticTracedAssignment[] {
return this.tracedAssignments;
}
Expand Down Expand Up @@ -347,6 +352,7 @@ export class LanguageParser {
variableNode.refId = node.refId;
variableNode.modifierChain = node.modifierChain;
variableNode.index = node.index;
this.createdVariables.push(variableNode);

return variableNode;
}
Expand Down Expand Up @@ -418,6 +424,7 @@ export class LanguageParser {
NodeHelpers.mergeVarRight(left, right);

newNodes.push(right);
this.createdVariables.push(right);

this.mergedVariablePaths.push(right);
this.mergedComponents.set(node, right);
Expand All @@ -444,7 +451,7 @@ export class LanguageParser {

NodeHelpers.mergeVarContentLeft(node.sourceTerminator + node.value + node.sourceTerminator, node, left);
NodeHelpers.mergeVarContentLeft(right.name, right, left);

this.createdVariables.push(left);
newNodes.push(left);
this.mergedVariablePaths.push(left);
this.mergedComponents.set(node, left);
Expand Down Expand Up @@ -511,6 +518,7 @@ export class LanguageParser {
varNodeWrap.content = operator.content;
varNodeWrap.name = operator.content;
varNodeWrap.originalAbstractNode = operator;
this.createdVariables.push(varNodeWrap);

return varNodeWrap;
}
Expand Down Expand Up @@ -2218,6 +2226,8 @@ export class LanguageParser {
varNode.endPosition = node.endPosition;
varNode.modifierChain = node.modifierChain;
varNode.originalAbstractNode = node;
this.createdVariables.push(varNode);

newNodes.push(varNode);
} else {
newNodes.push(node);
Expand Down

0 comments on commit d385c90

Please sign in to comment.