diff --git a/packages/code-analyzer-pmd-engine/pmd-rules/src/main/java/com/salesforce/security/pmd/html/DetectHardCodedCredentialsInAura.java b/packages/code-analyzer-pmd-engine/pmd-rules/src/main/java/com/salesforce/security/pmd/html/DetectHardCodedCredentialsInAura.java new file mode 100644 index 00000000..a9af2e7b --- /dev/null +++ b/packages/code-analyzer-pmd-engine/pmd-rules/src/main/java/com/salesforce/security/pmd/html/DetectHardCodedCredentialsInAura.java @@ -0,0 +1,61 @@ +package com.salesforce.security.pmd.html; + +import java.util.List; + +import net.sourceforge.pmd.lang.html.ast.ASTHtmlElement; +import net.sourceforge.pmd.lang.html.rule.AbstractHtmlRule; +import net.sourceforge.pmd.lang.rule.xpath.Attribute; + +import com.salesforce.security.pmd.utils.SecretsInPackageUtils; + +public class DetectHardCodedCredentialsInAura extends AbstractHtmlRule { + private static final String AURA_C_COMPONENT = "C:"; + private static final String AURA_HARDCODED_SECRET_VIOLATION = + "Detected a potential hard coded secret in aura:attribute \"%s\""; + + @Override + @SuppressWarnings("unchecked") + public Object visit(ASTHtmlElement node, Object data) { + detectHardCodedSecrets(node,data); + return super.visit(node, data); + } + + private void detectHardCodedSecrets(ASTHtmlElement htmlElement, Object data) { + String name=htmlElement.getNodeName(); + if (name.equalsIgnoreCase("aura:attribute")) { + detectSecretsInAuraAttrs(htmlElement, data); + } else if (name.toUpperCase().startsWith(AURA_C_COMPONENT)) { + detectSecretsInAuraComponent(htmlElement, data); + } + + } + + private void detectSecretsInAuraComponent(ASTHtmlElement component, Object data) { + List allAttrs=component.getAttributes(); + for (Attribute eachAttr: allAttrs) { + String attrName = eachAttr.getName(); + if (SecretsInPackageUtils.isAPotentialSecret(attrName)) { + this.asCtx(data).addViolationWithMessage(component, + String.format(AURA_HARDCODED_SECRET_VIOLATION, attrName)); + } + } + + } + + private void detectSecretsInAuraAttrs(ASTHtmlElement nextAttr, Object data) { + String attrName = nextAttr.getAttribute("name"); + String type = nextAttr.getAttribute("type"); + if (type!=null && //handles null pointer exception when type is not specified + (type.compareToIgnoreCase("string")!=0 && type.compareToIgnoreCase("list")!=0)) { + return; + } + String defaultValue = nextAttr.getAttribute("default"); + if (defaultValue==null || defaultValue.isEmpty()){ + return; + } + if (SecretsInPackageUtils.isAPotentialSecret(attrName)) { + this.asCtx(data).addViolationWithMessage(nextAttr, + String.format(AURA_HARDCODED_SECRET_VIOLATION, attrName)); + } + } +} diff --git a/packages/code-analyzer-pmd-engine/pmd-rules/src/main/java/com/salesforce/security/pmd/html/DetectUnescapedHtmlInAura.java b/packages/code-analyzer-pmd-engine/pmd-rules/src/main/java/com/salesforce/security/pmd/html/DetectUnescapedHtmlInAura.java new file mode 100644 index 00000000..d159593b --- /dev/null +++ b/packages/code-analyzer-pmd-engine/pmd-rules/src/main/java/com/salesforce/security/pmd/html/DetectUnescapedHtmlInAura.java @@ -0,0 +1,15 @@ +package com.salesforce.security.pmd.html; + +import net.sourceforge.pmd.lang.html.ast.ASTHtmlElement; +import net.sourceforge.pmd.lang.html.rule.AbstractHtmlRule; + +public class DetectUnescapedHtmlInAura extends AbstractHtmlRule { + @Override + @SuppressWarnings("unchecked") + public Object visit(ASTHtmlElement node, Object data) { + if (node.getNodeName().equalsIgnoreCase("aura:unescapedHtml")) { + this.asCtx(data).addViolation(node); // Message is defined in sfca/rulesets/AppExchange_html.xml file + } + return super.visit(node, data); + } +} \ No newline at end of file diff --git a/packages/code-analyzer-pmd-engine/pmd-rules/src/main/java/com/salesforce/security/pmd/utils/SecretsInPackageUtils.java b/packages/code-analyzer-pmd-engine/pmd-rules/src/main/java/com/salesforce/security/pmd/utils/SecretsInPackageUtils.java new file mode 100644 index 00000000..6532b9e5 --- /dev/null +++ b/packages/code-analyzer-pmd-engine/pmd-rules/src/main/java/com/salesforce/security/pmd/utils/SecretsInPackageUtils.java @@ -0,0 +1,104 @@ +package com.salesforce.security.pmd.utils; + +import java.util.List; + +public class SecretsInPackageUtils { + private static final List PRIVACY_FIELD_MAPPINGS_LIST = List.of( + "SSN", + "SOCIALSECURITY", + "SOCIAL_SECURITY", + "NATIONALID", + "NATIONAL_ID", + "NATIONAL_IDENTIFIER", + "NATIONALIDENTIFIER", + "DRIVERSLICENSE", + "DRIVERS_LICENSE", + "DRIVER_LICENSE", + "DRIVERLICENSE", + "PASSPORT", + "AADHAAR", + "AADHAR" //More? + ); + + private static final List AUTH_FIELD_MAPPINGS_LIST = List.of( + "KEY", // potentially high false +ve rate + "ACCESS", + "PASS", + "ENCRYPT", + "TOKEN", + "HASH", + "SECRET", + "SIGNATURE", + "SIGN", + "AUTH", //AUTHORIZATION,AUTHENTICATION,AUTHENTICATE,OAUTH + "AUTHORIZATION", + "AUTHENTICATION", + "AUTHENTICATE", + "BEARER", + "CRED", //cred, credential(s), + "REFRESH", // + "CERT", + "PRIVATE", + "PUBLIC", + "JWT" + ); + + private static final List POTENTIAL_SECERT_VARS_LIST = List.of( + "APIKEY", + "API_KEY", + "API-KEY", + "PASSWORD", + "PASSWD", + "ENCRYPT", + "TOKEN", + "HASH", + "SECRET", + "SIGNATURE", + "AUTHN", + "AUTHZ", + "OAUTH", + "AUTHORIZATION", + "AUTHENTICATION", + "AUTHENTICATE", + "BEARER", + "CREDS", //cred - has too many false +ve hits, credential(s), + "CREDENTIAL", + "REFRESHTOKEN", + "REFRESH_TOKEN", + "CERT", + "PRIVATE", + "SYMMETRICKEY", + "SYMMETRIC_KEY", + "ASYMMETRIC_KEY", + "ASYMMETRICKEY", + "JWT", + "SALT", + "COOKIE", + "SESSIONID", + "SESSION_ID", + "CREDITCARD", + "CREDIT_CARD" + ); + + private static boolean isAPartialMatchInList(String inputStr, List listOfStrings) { + String inputStrUpper = inputStr.toUpperCase(); + for (String eachStr : listOfStrings) { + if (inputStrUpper.contains(eachStr)) { + return true; + } + } + return false; + } + + public static boolean isAnAuthTokenField(String fieldName) { + return isAPartialMatchInList(fieldName.toUpperCase(), AUTH_FIELD_MAPPINGS_LIST); + } + + public static boolean isAnInsecurePrivacyField(String fieldName) { + return isAPartialMatchInList(fieldName.toUpperCase(), PRIVACY_FIELD_MAPPINGS_LIST); + } + + public static boolean isAPotentialSecret(String attrName) { + return isAPartialMatchInList(attrName, POTENTIAL_SECERT_VARS_LIST ); + } +} diff --git a/packages/code-analyzer-pmd-engine/pmd-rules/src/main/java/com/salesforce/security/pmd/xml/DetectSecretsInCustomObjects.java b/packages/code-analyzer-pmd-engine/pmd-rules/src/main/java/com/salesforce/security/pmd/xml/DetectSecretsInCustomObjects.java index a6f277ce..440abc17 100644 --- a/packages/code-analyzer-pmd-engine/pmd-rules/src/main/java/com/salesforce/security/pmd/xml/DetectSecretsInCustomObjects.java +++ b/packages/code-analyzer-pmd-engine/pmd-rules/src/main/java/com/salesforce/security/pmd/xml/DetectSecretsInCustomObjects.java @@ -3,7 +3,6 @@ import net.sourceforge.pmd.lang.xml.ast.internal.XmlParserImpl.RootXmlNode; import java.io.File; import java.io.IOException; -import java.util.List; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -20,48 +19,10 @@ import net.sourceforge.pmd.lang.rule.AbstractRule; import org.xml.sax.SAXException; +import com.salesforce.security.pmd.utils.SecretsInPackageUtils; + public class DetectSecretsInCustomObjects extends AbstractRule { - private static final List PRIVACY_FIELD_MAPPINGS_LIST = List.of( - "SSN", - "SOCIALSECURITY", - "SOCIAL_SECURITY", - "NATIONALID", - "NATIONAL_ID", - "NATIONAL_IDENTIFIER", - "NATIONALIDENTIFIER", - "DRIVERSLICENSE", - "DRIVERS_LICENSE", - "DRIVER_LICENSE", - "DRIVERLICENSE", - "PASSPORT", - "AADHAAR", - "AADHAR" //More? - ); - - private static final List AUTH_FIELD_MAPPINGS_LIST = List.of( - "KEY", // potentially high false +ve rate - "ACCESS", - "PASS", - "ENCRYPT", - "TOKEN", - "HASH", - "SECRET", - "SIGNATURE", - "SIGN", - "AUTH", //AUTHORIZATION,AUTHENTICATION,AUTHENTICATE,OAUTH - "AUTHORIZATION", - "AUTHENTICATION", - "AUTHENTICATE", - "BEARER", - "CRED", //cred, credential(s), - "REFRESH", // - "CERT", - "PRIVATE", - "PUBLIC", - "JWT" - ); - - public static final String VISIBILITY_XPATH_EXPR = "/CustomObject/visibility[text()=\"Public\"]"; + public static final String VISIBILITY_XPATH_EXPR = "/CustomObject/visibility[text()=\"Public\"]"; public static final String PRIVACY_FIELD_XPATH_EXPR = "/CustomField/type[text()!=\"EncryptedText\"]"; private static final String CUSTOM_SETTINGS_XPATH_EXPR = "/CustomObject/customSettingsType"; @@ -73,10 +34,10 @@ public void apply(Node target, RuleContext ctx) { return; } String fieldName = fieldNameFromFileName(fieldFileName); - if (isAnAuthTokenField(fieldName)) { + if (SecretsInPackageUtils.isAnAuthTokenField(fieldName)) { doObjectVisibilityCheck(ctx, target, fieldFileName); } - if (isAnInsecurePrivacyField(fieldName)) { + if (SecretsInPackageUtils.isAnInsecurePrivacyField(fieldName)) { checkFieldType(ctx, target, fieldName); } } @@ -157,25 +118,6 @@ private String getObjectFileName(String fieldFileName) { } } - public boolean isAnAuthTokenField(String fieldName) { - return isAPartialMatchInList(fieldName.toUpperCase(), AUTH_FIELD_MAPPINGS_LIST); - } - - public boolean isAnInsecurePrivacyField(String fieldName) { - return isAPartialMatchInList(fieldName.toUpperCase(), PRIVACY_FIELD_MAPPINGS_LIST); - } - - - private static boolean isAPartialMatchInList(String inputStr, List listOfStrings) { - String inputStrUpper = inputStr.toUpperCase(); - for (String eachStr : listOfStrings) { - if (inputStrUpper.contains(eachStr)) { - return true; - } - } - return false; - } - private static Document parseDocument(String xmlFile) throws ParserConfigurationException, SAXException, IOException { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setExpandEntityReferences(false); diff --git a/packages/code-analyzer-pmd-engine/pmd-rules/src/main/resources/sfca/rulesets/AppExchange_html.xml b/packages/code-analyzer-pmd-engine/pmd-rules/src/main/resources/sfca/rulesets/AppExchange_html.xml new file mode 100644 index 00000000..4794f853 --- /dev/null +++ b/packages/code-analyzer-pmd-engine/pmd-rules/src/main/resources/sfca/rulesets/AppExchange_html.xml @@ -0,0 +1,45 @@ + + + AppExchange Security Rules for HTML Language + + + + Detects use of hard coded credentials in Aura components. + 2 + + + + + Detects use of aura:unescapedHtml,which should be used cautiously. Developers should ensure that the unescapedHtml should not use tainted input to protect against XSS. + 2 + + + + + Detects instances of lwc:dom="manual" that could allow unintentional or malicious user input. Don't allow user input on these elements. + 3 + + + + + + + + \ No newline at end of file diff --git a/packages/code-analyzer-pmd-engine/pmd-rules/src/main/resources/sfca/rulesets/AppExchange_xml.xml b/packages/code-analyzer-pmd-engine/pmd-rules/src/main/resources/sfca/rulesets/AppExchange_xml.xml index dbc1a0fa..f63995f4 100644 --- a/packages/code-analyzer-pmd-engine/pmd-rules/src/main/resources/sfca/rulesets/AppExchange_xml.xml +++ b/packages/code-analyzer-pmd-engine/pmd-rules/src/main/resources/sfca/rulesets/AppExchange_xml.xml @@ -1,9 +1,9 @@ - - AppExchange Security Rules + AppExchange Security Rules for XML Language - + externalInfoUrl="https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/guide/rules-pmd-appexchange.html#avoiddisableprotocolsecurityremotesitesetting"> Detects if "Disable Protocol Security" setting is true. 3 @@ -118,6 +118,40 @@ + + Detects use of JavaScript-style URLs (javascript:) in components, such as web links and buttons. Avoid JavaScript-style URLs in managed packages. + 1 + + + + + + + + + + Detects use of custom JavaScript actions in web links. + 2 + + + + + + + + - + externalInfoUrl="https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/guide/rules-pmd-appexchange.html#usehttpscallbackurlconnectedapp"> Detects instances of an OAuth callback URL that uses HTTP. Use HTTPS instead. 3 diff --git a/packages/code-analyzer-pmd-engine/pmd-rules/src/test/java/sfca/rulesets/appexchange_html/AvoidHardCodedCredentialsInAuraTest.java b/packages/code-analyzer-pmd-engine/pmd-rules/src/test/java/sfca/rulesets/appexchange_html/AvoidHardCodedCredentialsInAuraTest.java new file mode 100644 index 00000000..83f5cd5d --- /dev/null +++ b/packages/code-analyzer-pmd-engine/pmd-rules/src/test/java/sfca/rulesets/appexchange_html/AvoidHardCodedCredentialsInAuraTest.java @@ -0,0 +1,16 @@ +package sfca.rulesets.appexchange_html; + +import net.sourceforge.pmd.test.SimpleAggregatorTst; + +public class AvoidHardCodedCredentialsInAuraTest extends SimpleAggregatorTst { + @Override + protected void setUp() { + // The test data xml file for this rule's test will always be in the resources directory using a naming + // convention based off the package for this test and the rule being tested: + // "resources//xml/.xml". + // In this case "sfca.rulesets.appexchange_html" is the package name of this test file. Thus, the associated + // test data xml file for this rule must be found at: + // "resource/sfca/rulesets/appexchange_html/xml/AvoidHardCodedCredentialsInAura.xml" + addRule("sfca/rulesets/AppExchange_html.xml", "AvoidHardCodedCredentialsInAura"); + } +} diff --git a/packages/code-analyzer-pmd-engine/pmd-rules/src/test/java/sfca/rulesets/appexchange_html/AvoidUnescapedHtmlInAuraTest.java b/packages/code-analyzer-pmd-engine/pmd-rules/src/test/java/sfca/rulesets/appexchange_html/AvoidUnescapedHtmlInAuraTest.java new file mode 100644 index 00000000..b918fb1f --- /dev/null +++ b/packages/code-analyzer-pmd-engine/pmd-rules/src/test/java/sfca/rulesets/appexchange_html/AvoidUnescapedHtmlInAuraTest.java @@ -0,0 +1,16 @@ +package sfca.rulesets.appexchange_html; + +import net.sourceforge.pmd.test.SimpleAggregatorTst; + +public class AvoidUnescapedHtmlInAuraTest extends SimpleAggregatorTst { + @Override + protected void setUp() { + // The test data xml file for this rule's test will always be in the resources directory using a naming + // convention based off the package for this test and the rule being tested: + // "resources//xml/.xml". + // In this case "sfca.rulesets.appexchange_html" is the package name of this test file. Thus, the associated + // test data xml file for this rule must be found at: + // "resource/sfca/rulesets/appexchange_html/xml/AvoidUnescapedHtmlInAura.xml" + addRule("sfca/rulesets/AppExchange_html.xml", "AvoidUnescapedHtmlInAura"); + } +} diff --git a/packages/code-analyzer-pmd-engine/pmd-rules/src/test/java/sfca/rulesets/appexchange_html/DetectUseLwcDomManualTest.java b/packages/code-analyzer-pmd-engine/pmd-rules/src/test/java/sfca/rulesets/appexchange_html/DetectUseLwcDomManualTest.java new file mode 100644 index 00000000..f9cd53cd --- /dev/null +++ b/packages/code-analyzer-pmd-engine/pmd-rules/src/test/java/sfca/rulesets/appexchange_html/DetectUseLwcDomManualTest.java @@ -0,0 +1,16 @@ +package sfca.rulesets.appexchange_html; + +import net.sourceforge.pmd.test.SimpleAggregatorTst; + +public class DetectUseLwcDomManualTest extends SimpleAggregatorTst { + @Override + protected void setUp() { + // The test data xml file for this rule's test will always be in the resources directory using a naming + // convention based off the package for this test and the rule being tested: + // "resources//xml/.xml". + // In this case "sfca.rulesets.appexchange_html" is the package name of this test file. Thus, the associated + // test data xml file for this rule must be found at: + // "resource/sfca/rulesets/appexchange_html/xml/DetectUseLwcDomManual.xml" + addRule("sfca/rulesets/AppExchange_html.xml", "DetectUseLwcDomManual"); + } +} diff --git a/packages/code-analyzer-pmd-engine/pmd-rules/src/test/java/sfca/rulesets/appexchange_xml/AvoidDisableProtocolSecurityTest.java b/packages/code-analyzer-pmd-engine/pmd-rules/src/test/java/sfca/rulesets/appexchange_xml/AvoidDisableProtocolSecurityRemoteSiteSettingTest.java similarity index 79% rename from packages/code-analyzer-pmd-engine/pmd-rules/src/test/java/sfca/rulesets/appexchange_xml/AvoidDisableProtocolSecurityTest.java rename to packages/code-analyzer-pmd-engine/pmd-rules/src/test/java/sfca/rulesets/appexchange_xml/AvoidDisableProtocolSecurityRemoteSiteSettingTest.java index c40e44be..98a3414f 100644 --- a/packages/code-analyzer-pmd-engine/pmd-rules/src/test/java/sfca/rulesets/appexchange_xml/AvoidDisableProtocolSecurityTest.java +++ b/packages/code-analyzer-pmd-engine/pmd-rules/src/test/java/sfca/rulesets/appexchange_xml/AvoidDisableProtocolSecurityRemoteSiteSettingTest.java @@ -2,7 +2,7 @@ import net.sourceforge.pmd.test.SimpleAggregatorTst; -public class AvoidDisableProtocolSecurityTest extends SimpleAggregatorTst { +public class AvoidDisableProtocolSecurityRemoteSiteSettingTest extends SimpleAggregatorTst { @Override protected void setUp() { // The test data xml file for this rule's test will always be in the resources directory using a naming @@ -10,7 +10,7 @@ protected void setUp() { // "resources//xml/.xml". // In this case "sfca.rulesets.appexchange_xml" is the package name of this test file. Thus, the associated test // data xml file for this rule must be found at: - // "resource/sfca/rulesets/appexchange_xml/xml/AvoidDisableProtocolSecurity.xml" - addRule("sfca/rulesets/AppExchange_xml.xml", "AvoidDisableProtocolSecurity"); + // "resource/sfca/rulesets/appexchange_xml/xml/AvoidDisableProtocolSecurityRemoteSiteSetting.xml" + addRule("sfca/rulesets/AppExchange_xml.xml", "AvoidDisableProtocolSecurityRemoteSiteSetting"); } } diff --git a/packages/code-analyzer-pmd-engine/pmd-rules/src/test/java/sfca/rulesets/appexchange_xml/AvoidJavaScriptInUrlsTest.java b/packages/code-analyzer-pmd-engine/pmd-rules/src/test/java/sfca/rulesets/appexchange_xml/AvoidJavaScriptInUrlsTest.java new file mode 100644 index 00000000..bf3fbca9 --- /dev/null +++ b/packages/code-analyzer-pmd-engine/pmd-rules/src/test/java/sfca/rulesets/appexchange_xml/AvoidJavaScriptInUrlsTest.java @@ -0,0 +1,16 @@ +package sfca.rulesets.appexchange_xml; + +import net.sourceforge.pmd.test.SimpleAggregatorTst; + +public class AvoidJavaScriptInUrlsTest extends SimpleAggregatorTst { + @Override + protected void setUp() { + // The test data xml file for this rule's test will always be in the resources directory using a naming + // convention based off the package for this test and the rule being tested: + // "resources//xml/.xml". + // In this case "sfca.rulesets.appexchange_xml" is the package name of this test file. Thus, the associated test + // data xml file for this rule must be found at: + // "resource/sfca/rulesets/appexchange_xml/xml/AvoidJavaScriptInUrls.xml" + addRule("sfca/rulesets/AppExchange_xml.xml", "AvoidJavaScriptInUrls"); + } +} diff --git a/packages/code-analyzer-pmd-engine/pmd-rules/src/test/java/sfca/rulesets/appexchange_xml/AvoidJavaScriptWebLinkTest.java b/packages/code-analyzer-pmd-engine/pmd-rules/src/test/java/sfca/rulesets/appexchange_xml/AvoidJavaScriptWebLinkTest.java new file mode 100644 index 00000000..66deac93 --- /dev/null +++ b/packages/code-analyzer-pmd-engine/pmd-rules/src/test/java/sfca/rulesets/appexchange_xml/AvoidJavaScriptWebLinkTest.java @@ -0,0 +1,16 @@ +package sfca.rulesets.appexchange_xml; + +import net.sourceforge.pmd.test.SimpleAggregatorTst; + +public class AvoidJavaScriptWebLinkTest extends SimpleAggregatorTst { + @Override + protected void setUp() { + // The test data xml file for this rule's test will always be in the resources directory using a naming + // convention based off the package for this test and the rule being tested: + // "resources//xml/.xml". + // In this case "sfca.rulesets.appexchange_xml" is the package name of this test file. Thus, the associated test + // data xml file for this rule must be found at: + // "resource/sfca/rulesets/appexchange_xml/xml/AvoidJavaScriptWebLink.xml" + addRule("sfca/rulesets/AppExchange_xml.xml", "AvoidJavaScriptWebLink"); + } +} diff --git a/packages/code-analyzer-pmd-engine/pmd-rules/src/test/java/sfca/rulesets/appexchange_xml/UseHttpsCallbackUrlTest.java b/packages/code-analyzer-pmd-engine/pmd-rules/src/test/java/sfca/rulesets/appexchange_xml/UseHttpsCallbackUrlConnectedAppTest.java similarity index 83% rename from packages/code-analyzer-pmd-engine/pmd-rules/src/test/java/sfca/rulesets/appexchange_xml/UseHttpsCallbackUrlTest.java rename to packages/code-analyzer-pmd-engine/pmd-rules/src/test/java/sfca/rulesets/appexchange_xml/UseHttpsCallbackUrlConnectedAppTest.java index b212073a..8a67a595 100644 --- a/packages/code-analyzer-pmd-engine/pmd-rules/src/test/java/sfca/rulesets/appexchange_xml/UseHttpsCallbackUrlTest.java +++ b/packages/code-analyzer-pmd-engine/pmd-rules/src/test/java/sfca/rulesets/appexchange_xml/UseHttpsCallbackUrlConnectedAppTest.java @@ -2,7 +2,7 @@ import net.sourceforge.pmd.test.SimpleAggregatorTst; -public class UseHttpsCallbackUrlTest extends SimpleAggregatorTst { +public class UseHttpsCallbackUrlConnectedAppTest extends SimpleAggregatorTst { @Override protected void setUp() { // The test data xml file for this rule's test will always be in the resources directory using a naming @@ -10,7 +10,7 @@ protected void setUp() { // "resources//xml/.xml". // In this case "sfca.rulesets.appexchange_xml" is the package name of this test file. Thus, the associated test // data xml file for this rule must be found at: - // "resource/sfca/rulesets/appexchange_xml/xml/UseHttpsCallbackUrl.xml" - addRule("sfca/rulesets/AppExchange_xml.xml", "UseHttpsCallbackUrl"); + // "resource/sfca/rulesets/appexchange_xml/xml/UseHttpsCallbackUrlConnectedApp.xml" + addRule("sfca/rulesets/AppExchange_xml.xml", "UseHttpsCallbackUrlConnectedApp"); } } diff --git a/packages/code-analyzer-pmd-engine/pmd-rules/src/test/resources/sfca/rulesets/appexchange_html/xml/AvoidHardCodedCredentialsInAura.xml b/packages/code-analyzer-pmd-engine/pmd-rules/src/test/resources/sfca/rulesets/appexchange_html/xml/AvoidHardCodedCredentialsInAura.xml new file mode 100644 index 00000000..acbdf195 --- /dev/null +++ b/packages/code-analyzer-pmd-engine/pmd-rules/src/test/resources/sfca/rulesets/appexchange_html/xml/AvoidHardCodedCredentialsInAura.xml @@ -0,0 +1,52 @@ + + + + + When hard coded credentials are found in direct attributess of Aura component, then report violation + 3 + 2,2,2 + + + + ]]> + + + + When there are no hard coded credentials are found in direct attributes of Aura component, then do not report violation + 0 + + + + ]]> + + + + When hard coded credentials are found in attributes of Aura component, then report violation + 3 + 2,3,4 + + + + + + ]]> + + + + When there are no hard coded credentials are found in attributes of Aura component, then do not report violation + 0 + + + + + ]]> + + + \ No newline at end of file diff --git a/packages/code-analyzer-pmd-engine/pmd-rules/src/test/resources/sfca/rulesets/appexchange_html/xml/AvoidUnescapedHtmlInAura.xml b/packages/code-analyzer-pmd-engine/pmd-rules/src/test/resources/sfca/rulesets/appexchange_html/xml/AvoidUnescapedHtmlInAura.xml new file mode 100644 index 00000000..00fc471b --- /dev/null +++ b/packages/code-analyzer-pmd-engine/pmd-rules/src/test/resources/sfca/rulesets/appexchange_html/xml/AvoidUnescapedHtmlInAura.xml @@ -0,0 +1,23 @@ + + + + + When unescapedHtml is used, then report violation + 2 + 5,6 + + + + + + + + + ]]> + + + \ No newline at end of file diff --git a/packages/code-analyzer-pmd-engine/pmd-rules/src/test/resources/sfca/rulesets/appexchange_html/xml/DetectUseLwcDomManual.xml b/packages/code-analyzer-pmd-engine/pmd-rules/src/test/resources/sfca/rulesets/appexchange_html/xml/DetectUseLwcDomManual.xml new file mode 100644 index 00000000..9e833526 --- /dev/null +++ b/packages/code-analyzer-pmd-engine/pmd-rules/src/test/resources/sfca/rulesets/appexchange_html/xml/DetectUseLwcDomManual.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/packages/code-analyzer-pmd-engine/pmd-rules/src/test/resources/sfca/rulesets/appexchange_xml/xml/AvoidDisableProtocolSecurity.xml b/packages/code-analyzer-pmd-engine/pmd-rules/src/test/resources/sfca/rulesets/appexchange_xml/xml/AvoidDisableProtocolSecurityRemoteSiteSetting.xml similarity index 100% rename from packages/code-analyzer-pmd-engine/pmd-rules/src/test/resources/sfca/rulesets/appexchange_xml/xml/AvoidDisableProtocolSecurity.xml rename to packages/code-analyzer-pmd-engine/pmd-rules/src/test/resources/sfca/rulesets/appexchange_xml/xml/AvoidDisableProtocolSecurityRemoteSiteSetting.xml diff --git a/packages/code-analyzer-pmd-engine/pmd-rules/src/test/resources/sfca/rulesets/appexchange_xml/xml/AvoidJavaScriptInUrls.xml b/packages/code-analyzer-pmd-engine/pmd-rules/src/test/resources/sfca/rulesets/appexchange_xml/xml/AvoidJavaScriptInUrls.xml new file mode 100644 index 00000000..b514c341 --- /dev/null +++ b/packages/code-analyzer-pmd-engine/pmd-rules/src/test/resources/sfca/rulesets/appexchange_xml/xml/AvoidJavaScriptInUrls.xml @@ -0,0 +1,44 @@ + + + + + When javascript in CustomPageWebLink url, then report violation + 1 + 3 + + + javascript:doSomething(); + + ]]> + + + + + When javascript in WebLink url, then report violation + 1 + 3 + + + javascript:helloWorld(); + + ]]> + + + + + When using normal url in CustomPageWebLink, then do not report violation + 0 + + + /apex/test + + ]]> + + + \ No newline at end of file diff --git a/packages/code-analyzer-pmd-engine/pmd-rules/src/test/resources/sfca/rulesets/appexchange_xml/xml/AvoidJavaScriptWebLink.xml b/packages/code-analyzer-pmd-engine/pmd-rules/src/test/resources/sfca/rulesets/appexchange_xml/xml/AvoidJavaScriptWebLink.xml new file mode 100644 index 00000000..ce123a88 --- /dev/null +++ b/packages/code-analyzer-pmd-engine/pmd-rules/src/test/resources/sfca/rulesets/appexchange_xml/xml/AvoidJavaScriptWebLink.xml @@ -0,0 +1,30 @@ + + + + + When openType is "onClickJavaScript" in WebLink, then report violation + 1 + 3 + + + onClickJavaScript + + ]]> + + + + When openType is not "onClickJavaScript" in WebLink, then do not report violation + 0 + + + sidebar + + ]]> + + + \ No newline at end of file diff --git a/packages/code-analyzer-pmd-engine/pmd-rules/src/test/resources/sfca/rulesets/appexchange_xml/xml/UseHttpsCallbackUrl.xml b/packages/code-analyzer-pmd-engine/pmd-rules/src/test/resources/sfca/rulesets/appexchange_xml/xml/UseHttpsCallbackUrlConnectedApp.xml similarity index 84% rename from packages/code-analyzer-pmd-engine/pmd-rules/src/test/resources/sfca/rulesets/appexchange_xml/xml/UseHttpsCallbackUrl.xml rename to packages/code-analyzer-pmd-engine/pmd-rules/src/test/resources/sfca/rulesets/appexchange_xml/xml/UseHttpsCallbackUrlConnectedApp.xml index 7657427e..a7c1ae5d 100644 --- a/packages/code-analyzer-pmd-engine/pmd-rules/src/test/resources/sfca/rulesets/appexchange_xml/xml/UseHttpsCallbackUrl.xml +++ b/packages/code-analyzer-pmd-engine/pmd-rules/src/test/resources/sfca/rulesets/appexchange_xml/xml/UseHttpsCallbackUrlConnectedApp.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.net/rule-tests_1_0_0.xsd"> - If Connected App has unsafe callback, then report violation + When Connected App has unsafe callback, then report violation 1 6 - If Connected App has even just one unsafe callback url, then report violation + When Connected App has even just one unsafe callback url, then report violation 1 6 - Connected App with unsafe callback url False positive + When Connected App has safe callback url, then do not report violation 0 diff --git a/packages/code-analyzer-pmd-engine/src/constants.ts b/packages/code-analyzer-pmd-engine/src/constants.ts index c10e0f5e..673fd9e4 100644 --- a/packages/code-analyzer-pmd-engine/src/constants.ts +++ b/packages/code-analyzer-pmd-engine/src/constants.ts @@ -34,7 +34,9 @@ export const DEFAULT_FILE_EXTENSIONS: Record = { [Language.HTML]: [ // From PMD's HtmlLanguageModule: - '.html', '.htm', '.xhtml', '.xht', '.shtml' + '.html', '.htm', '.xhtml', '.xht', '.shtml', + // For the AppExchange rules - to support rules for aura components + '.cmp' ], [Language.JAVASCRIPT]: [ @@ -65,6 +67,7 @@ export const DEFAULT_FILE_EXTENSIONS: Record = { // the user needing to add it to their custom_rulesets configuration list. See "pmd-rules/src/main/resources" to see // which rulesets we have bundled inside our sfca-pmd-rules jar file. export const SFCA_RULESETS_TO_MAKE_AVAILABLE: string[] = [ + "sfca/rulesets/AppExchange_html.xml", "sfca/rulesets/AppExchange_xml.xml" ]; diff --git a/packages/code-analyzer-pmd-engine/src/pmd-rule-mappings.ts b/packages/code-analyzer-pmd-engine/src/pmd-rule-mappings.ts index ebc30dc2..2fbd34f8 100644 --- a/packages/code-analyzer-pmd-engine/src/pmd-rule-mappings.ts +++ b/packages/code-analyzer-pmd-engine/src/pmd-rule-mappings.ts @@ -395,6 +395,25 @@ export const RULE_MAPPINGS: Record