-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NEW: @W-17310939@: Add in our first AppExchange security rule... #173
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<ruleset name="AppExchange" | ||
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd"> | ||
<description>AppExchange Security Rules</description> | ||
|
||
<rule name="AvoidInsecureHttpRemoteSiteSetting" | ||
language="xml" | ||
class="net.sourceforge.pmd.lang.rule.xpath.XPathRule" | ||
message="Avoid using insecure http urls in Remote Site Settings."> | ||
<!-- TODO: NEED TO ADD IN externalInfoUrl ONCE WE HAVE A PERMANENT LOCATION FOR THE DOC PAGE --> | ||
<description>Detects instances of a Remote Site Settings that use HTTP.Use HTTPS instead.</description> | ||
<priority>3</priority> | ||
<properties> | ||
<property name="xpath"> | ||
<value> | ||
<![CDATA[ | ||
/document/RemoteSiteSetting/url/text[starts-with(lower-case(@Text),"http://")] | ||
]]> | ||
</value> | ||
</property> | ||
</properties> | ||
</rule> | ||
|
||
|
||
</ruleset> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package sfca.rulesets.appexchange_xml; | ||
|
||
import net.sourceforge.pmd.test.SimpleAggregatorTst; | ||
|
||
public class AvoidInsecureHttpRemoteSiteSettingTest 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/<TestPackageName>/xml/<RuleName>.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/AvoidInsecureHttpRemoteSiteSetting.xml" | ||
addRule("sfca/rulesets/AppExchange_xml.xml", "AvoidInsecureHttpRemoteSiteSetting"); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<test-data | ||
xmlns="http://pmd.sourceforge.net/rule-tests" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests https://pmd.sourceforge.net/rule-tests_1_0_0.xsd"> | ||
|
||
<test-code> | ||
<description>When url contains http then violation should be reported</description> | ||
<expected-problems>1</expected-problems> | ||
<expected-linenumbers>6</expected-linenumbers> | ||
<expected-messages> | ||
<message>Avoid using insecure http urls in Remote Site Settings.</message> | ||
</expected-messages> | ||
<code><![CDATA[ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<RemoteSiteSetting xmlns="http://soap.sforce.com/2006/04/metadata"> | ||
<description>Used for Apex callout to mapping web service</description> | ||
<disableProtocolSecurity>false</disableProtocolSecurity> | ||
<isActive>true</isActive> | ||
<url>http://www.maptestsite.net/mapping1</url> | ||
</RemoteSiteSetting> | ||
]]></code> | ||
</test-code> | ||
|
||
<test-code> | ||
<description>When url contains https then violation should not be reported</description> | ||
<expected-problems>0</expected-problems> | ||
<code><![CDATA[ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<RemoteSiteSetting xmlns="http://soap.sforce.com/2006/04/metadata"> | ||
<description>Used for Apex callout to mapping web service</description> | ||
<disableProtocolSecurity>false</disableProtocolSecurity> | ||
<isActive>true</isActive> | ||
<url>https://www.maptestsite.net/mapping1</url> | ||
</RemoteSiteSetting> | ||
]]></code> | ||
</test-code> | ||
|
||
</test-data> |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -312,14 +312,14 @@ abstract class SharedConfigValueExtractor { | |
const extToLangMap: Map<string, Language> = new Map(); // To keep track if file extension shows up with more than one language | ||
const fileExtensionsMap: Record<Language, string[]> = {... DEFAULT_FILE_EXTENSIONS}; // Start with copy | ||
for (const language of Object.keys(fileExtensionsMap) as Language[]) { | ||
const fileExts: string[] = makeUnique(fileExtensionsExtractor.extractArray(language, | ||
const fileExts: string[] = makeUniqueCaseInsensitive(fileExtensionsExtractor.extractArray(language, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since the AppExchange rules will need to add in more default file_extensions like But things still work case insensitive as we expect. But it did require me to change the makeUnique function to be a makeUniqueCaseInsensitive routine instead. |
||
(element, elementFieldPath) => ValueValidator.validateString(element, | ||
elementFieldPath, FILE_EXT_PATTERN), | ||
DEFAULT_FILE_EXTENSIONS[language] | ||
)!).map(fileExt => fileExt.toLowerCase()); | ||
)!); | ||
|
||
// Validate that none of the file extensions already exist in another language | ||
for (const fileExt of fileExts) { | ||
for (const fileExt of fileExts.map(fileExt => fileExt.toLowerCase())) { | ||
if (extToLangMap.has(fileExt) && extToLangMap.get(fileExt) !== language) { | ||
throw new Error(getMessage('InvalidFileExtensionDueToItBeingListedTwice', | ||
fileExtensionsExtractor.getFieldPath(), fileExt, | ||
|
@@ -427,6 +427,14 @@ function toAvailableLanguagesText(languages: string[]): string { | |
.join(', ').replace(`'javascript'`, `'javascript' (or 'ecmascript')`); | ||
} | ||
|
||
export function makeUnique(values: string[]): string[] { | ||
return [...new Set(values)]; | ||
export function makeUniqueCaseInsensitive(arr: string[]): string[] { | ||
const seen = new Set<string>(); | ||
return arr.filter((str) => { | ||
const lowerStr = str.toLowerCase(); | ||
if (seen.has(lowerStr)) { | ||
return false; | ||
} | ||
seen.add(lowerStr); | ||
return true; | ||
}); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I got this example right from https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_remotesitesetting.htm