From c0e59735173260c06ea5e1ef4ed1c80ee8451244 Mon Sep 17 00:00:00 2001 From: bjiang Date: Fri, 6 May 2016 15:50:35 -0400 Subject: [PATCH 1/8] rename RubyBundlerAnalyzer and javadoc --- ...Analyzer.java => RubyBundlerAnalyzer.java} | 43 ++++++++++++++++--- ...rg.owasp.dependencycheck.analyzer.Analyzer | 2 +- 2 files changed, 38 insertions(+), 7 deletions(-) rename dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/{RubyBundleInstallDeploymentAnalyzer.java => RubyBundlerAnalyzer.java} (53%) diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundleInstallDeploymentAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.java similarity index 53% rename from dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundleInstallDeploymentAnalyzer.java rename to dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.java index b7f0262f8..7ec6c9207 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundleInstallDeploymentAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.java @@ -1,3 +1,20 @@ +/* + * This file is part of dependency-check-core. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (c) 2016 Bianca Jiang. All Rights Reserved. + */ package org.owasp.dependencycheck.analyzer; import java.io.File; @@ -7,16 +24,30 @@ import org.owasp.dependencycheck.Engine; import org.owasp.dependencycheck.analyzer.exception.AnalysisException; import org.owasp.dependencycheck.dependency.Dependency; -public class RubyBundleInstallDeploymentAnalyzer extends RubyGemspecAnalyzer { +/** + * Used to leverage Ruby gems that are deployed or installed by Ruby bundler (http://bundler.io). + * The difference of scanning gems installed by the bundler is that "bundle install" creates + * a set of new .gemspec files under a folder called "specifications", in addition to the original + * .gemspec files from source. The advantage of bundler generated .gemspec files is that + * they contain fully resolved attributes, and original .gemspec from source often contain variable + * for attributes. + * + * This analyzer takes advantage of the fully resolved .gemspec installed by the bundler for + * better dependency identification results. It also tries to resolve the dependency packagePath + * to where the gem is actually installed. Then during AnalysisPhase.PRE_FINDING_ANALYSIS + * DependencyBundlingAnalyzer would merge the two dependencies together if they contain + * the same packagePath. + * + * @author Bianca Jiang (biancajiang@gmail.com) + */ +public class RubyBundlerAnalyzer extends RubyGemspecAnalyzer { + //Folder name that contains .gemspec files created by "bundle install" private static final String SPECIFICATIONS = "specifications"; + + //Folder name that contains the gems by "bundle install" private static final String GEMS = "gems"; - /** - * The logger. - */ -// private static final Logger LOGGER = LoggerFactory.getLogger(RubyBundleInstallDeploymentAnalyzer.class); - /** * Only accept *.gemspec stubs generated by "bundle install --deployment" under "specifications" folder. */ diff --git a/dependency-check-core/src/main/resources/META-INF/services/org.owasp.dependencycheck.analyzer.Analyzer b/dependency-check-core/src/main/resources/META-INF/services/org.owasp.dependencycheck.analyzer.Analyzer index b0d1c95c8..7f67a3d84 100644 --- a/dependency-check-core/src/main/resources/META-INF/services/org.owasp.dependencycheck.analyzer.Analyzer +++ b/dependency-check-core/src/main/resources/META-INF/services/org.owasp.dependencycheck.analyzer.Analyzer @@ -19,6 +19,6 @@ org.owasp.dependencycheck.analyzer.OpenSSLAnalyzer org.owasp.dependencycheck.analyzer.CMakeAnalyzer org.owasp.dependencycheck.analyzer.NodePackageAnalyzer org.owasp.dependencycheck.analyzer.RubyGemspecAnalyzer -org.owasp.dependencycheck.analyzer.RubyBundleInstallDeploymentAnalyzer +org.owasp.dependencycheck.analyzer.RubyBundlerAnalyzer org.owasp.dependencycheck.analyzer.RubyBundleAuditAnalyzer org.owasp.dependencycheck.analyzer.ComposerLockAnalyzer From 94c6778b8935074f963bf1b2fea6ab9b38436b70 Mon Sep 17 00:00:00 2001 From: bjiang Date: Fri, 6 May 2016 16:14:16 -0400 Subject: [PATCH 2/8] better javadoc --- .../analyzer/RubyBundlerAnalyzer.java | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.java index 7ec6c9207..0725d8202 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.java @@ -23,20 +23,24 @@ import java.io.FilenameFilter; import org.owasp.dependencycheck.Engine; import org.owasp.dependencycheck.analyzer.exception.AnalysisException; import org.owasp.dependencycheck.dependency.Dependency; +import org.owasp.dependencycheck.utils.Settings; /** * Used to leverage Ruby gems that are deployed or installed by Ruby bundler (http://bundler.io). - * The difference of scanning gems installed by the bundler is that "bundle install" creates - * a set of new .gemspec files under a folder called "specifications", in addition to the original - * .gemspec files from source. The advantage of bundler generated .gemspec files is that - * they contain fully resolved attributes, and original .gemspec from source often contain variable - * for attributes. + * Ruby bundler creates new .gemspec files under a folder called "specifications" at deploy time, + * in addition to the original .gemspec files from source. The advantage of bundler generated + * .gemspec files is that they contain fully resolved attributes thus provides more accurate + * evidences, whereas the original .gemspec from source often contain variables for attributes + * that can't be used for evidences. * - * This analyzer takes advantage of the fully resolved .gemspec installed by the bundler for - * better dependency identification results. It also tries to resolve the dependency packagePath + * This analyzer accepts the fully resolved .gemspec installed by the bundler for + * better evidence results. It also tries to resolve the dependency packagePath * to where the gem is actually installed. Then during AnalysisPhase.PRE_FINDING_ANALYSIS - * DependencyBundlingAnalyzer would merge the two dependencies together if they contain - * the same packagePath. + * DependencyBundlingAnalyzer would merge two .gemspec dependencies together if + * Dependency.getPackagePath() are the same. + * + * Note this analyzer share the same Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED as + * RubyGemspecAnalyzer, so it will enabled/disabled with RubyGemspecAnalyzer. * * @author Bianca Jiang (biancajiang@gmail.com) */ @@ -49,7 +53,7 @@ public class RubyBundlerAnalyzer extends RubyGemspecAnalyzer { private static final String GEMS = "gems"; /** - * Only accept *.gemspec stubs generated by "bundle install --deployment" under "specifications" folder. + * Only accept *.gemspec files generated by "bundle install --deployment" under "specifications" folder. */ @Override public boolean accept(File pathname) { From 8a42fe4ae1d0bcc9bdceba58c9e34fa0f3d73f0f Mon Sep 17 00:00:00 2001 From: bjiang Date: Fri, 6 May 2016 16:19:59 -0400 Subject: [PATCH 3/8] javadoc --- .../analyzer/RubyBundlerAnalyzer.java | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.java index 0725d8202..b74f05e90 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.java @@ -23,22 +23,20 @@ import java.io.FilenameFilter; import org.owasp.dependencycheck.Engine; import org.owasp.dependencycheck.analyzer.exception.AnalysisException; import org.owasp.dependencycheck.dependency.Dependency; -import org.owasp.dependencycheck.utils.Settings; /** - * Used to leverage Ruby gems that are deployed or installed by Ruby bundler (http://bundler.io). - * Ruby bundler creates new .gemspec files under a folder called "specifications" at deploy time, - * in addition to the original .gemspec files from source. The advantage of bundler generated - * .gemspec files is that they contain fully resolved attributes thus provides more accurate - * evidences, whereas the original .gemspec from source often contain variables for attributes - * that can't be used for evidences. - * - * This analyzer accepts the fully resolved .gemspec installed by the bundler for - * better evidence results. It also tries to resolve the dependency packagePath + * This analyzer accepts the fully resolved .gemspec created by the Ruby bundler (http://bundler.io) + * for better evidence results. It also tries to resolve the dependency packagePath * to where the gem is actually installed. Then during AnalysisPhase.PRE_FINDING_ANALYSIS * DependencyBundlingAnalyzer would merge two .gemspec dependencies together if * Dependency.getPackagePath() are the same. * + * Ruby bundler creates new .gemspec files under a folder called "specifications" at deploy time, + * in addition to the original .gemspec files from source. The bundler generated + * .gemspec files always contain fully resolved attributes thus provide more accurate + * evidences, whereas the original .gemspec from source often contain variables for attributes + * that can't be used for evidences. + * * Note this analyzer share the same Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED as * RubyGemspecAnalyzer, so it will enabled/disabled with RubyGemspecAnalyzer. * From 83ab122ddf7862bdc9053a37874d1767c2f77ef1 Mon Sep 17 00:00:00 2001 From: bjiang Date: Fri, 6 May 2016 16:42:39 -0400 Subject: [PATCH 4/8] disable RubyBundlerAnalyzer if RubyBundleAuditAnalyzer --- .../analyzer/RubyBundleAuditAnalyzer.java | 34 +++++++++++-------- .../analyzer/RubyBundleAuditAnalyzerTest.java | 2 -- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.java index d95c1a7cc..8a315bd42 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.java @@ -203,21 +203,25 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer { @Override protected void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException { -// if (needToDisableGemspecAnalyzer) { -// boolean failed = true; -// final String className = RubyGemspecAnalyzer.class.getName(); -// for (FileTypeAnalyzer analyzer : engine.getFileTypeAnalyzers()) { -// if (analyzer instanceof RubyGemspecAnalyzer) { -// ((RubyGemspecAnalyzer) analyzer).setEnabled(false); -// LOGGER.info("Disabled " + className + " to avoid noisy duplicate results."); -// failed = false; -// } -// } -// if (failed) { -// LOGGER.warn("Did not find" + className + '.'); -// } -// needToDisableGemspecAnalyzer = false; -// } + if (needToDisableGemspecAnalyzer) { + boolean failed = true; + final String className = RubyGemspecAnalyzer.class.getName(); + for (FileTypeAnalyzer analyzer : engine.getFileTypeAnalyzers()) { + if (analyzer instanceof RubyBundlerAnalyzer) { + ((RubyBundlerAnalyzer) analyzer).setEnabled(false); + LOGGER.info("Disabled " + RubyBundlerAnalyzer.class.getName() + " to avoid noisy duplicate results."); + } + else if (analyzer instanceof RubyGemspecAnalyzer) { + ((RubyGemspecAnalyzer) analyzer).setEnabled(false); + LOGGER.info("Disabled " + className + " to avoid noisy duplicate results."); + failed = false; + } + } + if (failed) { + LOGGER.warn("Did not find " + className + '.'); + } + needToDisableGemspecAnalyzer = false; + } final File parentFile = dependency.getActualFile().getParentFile(); final Process process = launchBundleAudit(parentFile); try { diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzerTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzerTest.java index 70dd14d4c..04f167703 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzerTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzerTest.java @@ -181,9 +181,7 @@ public class RubyBundleAuditAnalyzerTest extends BaseTest { final Engine engine = new Engine(); engine.scan(BaseTest.getResourceAsFile(this, -// "ruby/vulnerable/gems/chef-12.8.4/")); "ruby/vulnerable/gems/rails-4.1.15/")); -// "java")); engine.analyzeDependencies(); List dependencies = engine.getDependencies(); From 06dad8f79cf541653e9712c65f3a1bd4286adea3 Mon Sep 17 00:00:00 2001 From: bjiang Date: Fri, 6 May 2016 17:22:39 -0400 Subject: [PATCH 5/8] javadoc --- .../dependencycheck/analyzer/RubyBundlerAnalyzer.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.java index b74f05e90..5452aa209 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.java @@ -27,8 +27,8 @@ import org.owasp.dependencycheck.dependency.Dependency; /** * This analyzer accepts the fully resolved .gemspec created by the Ruby bundler (http://bundler.io) * for better evidence results. It also tries to resolve the dependency packagePath - * to where the gem is actually installed. Then during AnalysisPhase.PRE_FINDING_ANALYSIS - * DependencyBundlingAnalyzer would merge two .gemspec dependencies together if + * to where the gem is actually installed. Then during {@link AnalysisPhase.PRE_FINDING_ANALYSIS} + * {@link DependencyBundlingAnalyzer} will merge two .gemspec dependencies together if * Dependency.getPackagePath() are the same. * * Ruby bundler creates new .gemspec files under a folder called "specifications" at deploy time, @@ -37,8 +37,8 @@ import org.owasp.dependencycheck.dependency.Dependency; * evidences, whereas the original .gemspec from source often contain variables for attributes * that can't be used for evidences. * - * Note this analyzer share the same Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED as - * RubyGemspecAnalyzer, so it will enabled/disabled with RubyGemspecAnalyzer. + * Note this analyzer share the same {@link Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED} as + * {@link RubyGemspecAnalyzer}, so it will enabled/disabled with {@link RubyGemspecAnalyzer}. * * @author Bianca Jiang (biancajiang@gmail.com) */ From b0f4ab9ba558829052cd58ddd413beee6fb3c48f Mon Sep 17 00:00:00 2001 From: bjiang Date: Fri, 6 May 2016 17:25:08 -0400 Subject: [PATCH 6/8] cleanup & Rakefile support placeholder --- .../analyzer/RubyGemspecAnalyzer.java | 18 +++--------------- .../analyzer/RubyGemspecAnalyzerTest.java | 13 +++++++++++++ 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyGemspecAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyGemspecAnalyzer.java index 7bec4c505..8bad7cab2 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyGemspecAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyGemspecAnalyzer.java @@ -57,11 +57,13 @@ public class RubyGemspecAnalyzer extends AbstractFileTypeAnalyzer { private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(GEMSPEC).build(); + //TODO: support Rakefile + //= FileFilterBuilder.newInstance().addExtensions(GEMSPEC).addFilenames("Rakefile").build(); private static final String VERSION_FILE_NAME = "VERSION"; /** - * @return a filter that accepts files named Rakefile or matching the glob pattern, *.gemspec + * @return a filter that accepts files matching the glob pattern, *.gemspec */ @Override protected FileFilter getFileFilter() { @@ -133,11 +135,7 @@ public class RubyGemspecAnalyzer extends AbstractFileTypeAnalyzer { addStringEvidence(product, contents, blockVariable, "summary", "summary", Confidence.LOW); addStringEvidence(vendor, contents, blockVariable, "author", "authors?", Confidence.HIGHEST); -// addListEvidence(vendor, contents, blockVariable, "authors", Confidence.HIGHEST); addStringEvidence(vendor, contents, blockVariable, "email", "emails?", Confidence.MEDIUM); -// if (email.isEmpty()) { -// addListEvidence(vendor, contents, blockVariable, EMAIL, Confidence.MEDIUM); -// } addStringEvidence(vendor, contents, blockVariable, "homepage", "homepage", Confidence.HIGHEST); addStringEvidence(vendor, contents, blockVariable, "license", "licen[cs]es?", Confidence.HIGHEST); @@ -149,16 +147,6 @@ public class RubyGemspecAnalyzer extends AbstractFileTypeAnalyzer { setPackagePath(dependency); } -// private void addListEvidence(EvidenceCollection evidences, String contents, -// String blockVariable, String field, Confidence confidence) { -// final Matcher matcher = Pattern.compile( -// String.format("\\s+?%s\\.%s\\s*?=\\s*?\\[(.*?)\\]", blockVariable, field)).matcher(contents); -// if (matcher.find()) { -// final String value = matcher.group(1).replaceAll("['\"]", " ").trim(); -// evidences.addEvidence(GEMSPEC, field, value, confidence); -// } -// } - private String addStringEvidence(EvidenceCollection evidences, String contents, String blockVariable, String field, String fieldPattern, Confidence confidence) { String value = ""; diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/RubyGemspecAnalyzerTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/RubyGemspecAnalyzerTest.java index 6f4f7578b..882a70ef7 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/RubyGemspecAnalyzerTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/RubyGemspecAnalyzerTest.java @@ -100,4 +100,17 @@ public class RubyGemspecAnalyzerTest extends BaseTest { assertThat(result.getProductEvidence().toString(), containsString("rest-client")); assertThat(result.getVersionEvidence().toString(), containsString("1.7.2")); } + + /** + * Test Rakefile analysis. + * + * @throws AnalysisException is thrown when an exception occurs. + */ + //@Test TODO: place holder to test Rakefile support + public void testAnalyzeRakefile() throws AnalysisException { + final Dependency result = new Dependency(BaseTest.getResourceAsFile(this, + "ruby/vulnerable/gems/rails-4.1.15/vendor/bundle/ruby/2.2.0/gems/pg-0.18.4/Rakefile")); + analyzer.analyze(result, null); + //TODO add verification + } } From 83f83d4eeeaa4f7369875a64c0b5c3fdc6604d9d Mon Sep 17 00:00:00 2001 From: bjiang Date: Fri, 6 May 2016 17:45:40 -0400 Subject: [PATCH 7/8] add RubyBundlerAnalyzerTest --- .../analyzer/RubyBundlerAnalyzer.java | 7 +- .../analyzer/RubyBundlerAnalyzerTest.java | 105 +++++++++ .../bundle/ruby/2.2.0/gems/pg-0.18.4/Rakefile | 218 ++++++++++++++++++ .../2.2.0/specifications/dalli-2.7.5.gemspec | 54 +++++ 4 files changed, 383 insertions(+), 1 deletion(-) create mode 100644 dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzerTest.java create mode 100644 dependency-check-core/src/test/resources/ruby/vulnerable/gems/rails-4.1.15/vendor/bundle/ruby/2.2.0/gems/pg-0.18.4/Rakefile create mode 100644 dependency-check-core/src/test/resources/ruby/vulnerable/gems/rails-4.1.15/vendor/bundle/ruby/2.2.0/specifications/dalli-2.7.5.gemspec diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.java index 5452aa209..6d17f7aa1 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.java @@ -43,7 +43,12 @@ import org.owasp.dependencycheck.dependency.Dependency; * @author Bianca Jiang (biancajiang@gmail.com) */ public class RubyBundlerAnalyzer extends RubyGemspecAnalyzer { - + + /** + * The name of the analyzer. + */ + private static final String ANALYZER_NAME = "Ruby Bundler Analyzer"; + //Folder name that contains .gemspec files created by "bundle install" private static final String SPECIFICATIONS = "specifications"; diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzerTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzerTest.java new file mode 100644 index 000000000..bff57eeff --- /dev/null +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzerTest.java @@ -0,0 +1,105 @@ +/* + * This file is part of dependency-check-core. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (c) 2016 Bianca Jiang. All Rights Reserved. + */ +package org.owasp.dependencycheck.analyzer; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.owasp.dependencycheck.BaseTest; +import org.owasp.dependencycheck.analyzer.exception.AnalysisException; +import org.owasp.dependencycheck.dependency.Dependency; + +import java.io.File; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.*; + +/** + * Unit tests for {@link RubyBundlerAnalyzer}. + * + * @author Bianca Jiang + */ +public class RubyBundlerAnalyzerTest extends BaseTest { + + /** + * The analyzer to test. + */ + RubyBundlerAnalyzer analyzer; + + /** + * Correctly setup the analyzer for testing. + * + * @throws Exception thrown if there is a problem + */ + @Before + public void setUp() throws Exception { + analyzer = new RubyBundlerAnalyzer(); + analyzer.setFilesMatched(true); + analyzer.initialize(); + } + + /** + * Cleanup the analyzer's temp files, etc. + * + * @throws Exception thrown if there is a problem + */ + @After + public void tearDown() throws Exception { + analyzer.close(); + analyzer = null; + } + + /** + * Test Analyzer name. + */ + @Test + public void testGetName() { + assertThat(analyzer.getName(), is("Ruby Bundler Analyzer")); + } + + /** + * Test Ruby Gemspec file support. + */ + @Test + public void testSupportsFiles() { + assertThat(analyzer.accept(new File("test.gemspec")), is(true)); + } + + /** + * Test Ruby Bundler created gemspec analysis. + * + * @throws AnalysisException is thrown when an exception occurs. + */ + @Test + public void testAnalyzeGemspec() throws AnalysisException { + final Dependency result = new Dependency(BaseTest.getResourceAsFile(this, + "ruby/vulnerable/gems/rails-4.1.15/vendor/bundle/ruby/2.2.0/specifications/dalli-2.7.5.gemspec")); + analyzer.analyze(result, null); + + final String vendorString = result.getVendorEvidence().toString(); + assertThat(vendorString, containsString("Peter M. Goldstein")); + assertThat(vendorString, containsString("Mike Perham")); + assertThat(vendorString, containsString("peter.m.goldstein@gmail.com")); + assertThat(vendorString, containsString("https://github.com/petergoldstein/dalli")); + assertThat(vendorString, containsString("MIT")); + assertThat(result.getProductEvidence().toString(), containsString("dalli")); + assertThat(result.getProductEvidence().toString(), containsString("High performance memcached client for Ruby")); + assertThat(result.getVersionEvidence().toString(), containsString("2.7.5")); + } +} diff --git a/dependency-check-core/src/test/resources/ruby/vulnerable/gems/rails-4.1.15/vendor/bundle/ruby/2.2.0/gems/pg-0.18.4/Rakefile b/dependency-check-core/src/test/resources/ruby/vulnerable/gems/rails-4.1.15/vendor/bundle/ruby/2.2.0/gems/pg-0.18.4/Rakefile new file mode 100644 index 000000000..4c6baeada --- /dev/null +++ b/dependency-check-core/src/test/resources/ruby/vulnerable/gems/rails-4.1.15/vendor/bundle/ruby/2.2.0/gems/pg-0.18.4/Rakefile @@ -0,0 +1,218 @@ +#!/usr/bin/env rake + +require 'rbconfig' +require 'pathname' +require 'tmpdir' + +begin + require 'rake/extensiontask' +rescue LoadError + abort "This Rakefile requires rake-compiler (gem install rake-compiler)" +end + +begin + require 'hoe' +rescue LoadError + abort "This Rakefile requires hoe (gem install hoe)" +end + +require 'rake/clean' + +# Build directory constants +BASEDIR = Pathname( __FILE__ ).dirname +SPECDIR = BASEDIR + 'spec' +LIBDIR = BASEDIR + 'lib' +EXTDIR = BASEDIR + 'ext' +PKGDIR = BASEDIR + 'pkg' +TMPDIR = BASEDIR + 'tmp' + +DLEXT = RbConfig::CONFIG['DLEXT'] +EXT = LIBDIR + "pg_ext.#{DLEXT}" + +GEMSPEC = 'pg.gemspec' + +TEST_DIRECTORY = BASEDIR + "tmp_test_specs" + +CLOBBER.include( TEST_DIRECTORY.to_s ) +CLEAN.include( PKGDIR.to_s, TMPDIR.to_s ) + +# Set up Hoe plugins +Hoe.plugin :mercurial +Hoe.plugin :signing +Hoe.plugin :deveiate +Hoe.plugin :bundler + +Hoe.plugins.delete :rubyforge +Hoe.plugins.delete :compiler + +load 'Rakefile.cross' + + +# Hoe specification +$hoespec = Hoe.spec 'pg' do + self.readme_file = 'README.rdoc' + self.history_file = 'History.rdoc' + self.extra_rdoc_files = Rake::FileList[ '*.rdoc' ] + self.extra_rdoc_files.include( 'POSTGRES', 'LICENSE' ) + self.extra_rdoc_files.include( 'ext/*.c' ) + self.license :BSD + + self.developer 'Michael Granger', 'ged@FaerieMUD.org' + self.developer 'Lars Kanis', 'lars@greiz-reinsdorf.de' + + self.dependency 'rake-compiler', '~> 0.9', :developer + self.dependency 'rake-compiler-dock', '~> 0.3', :developer + self.dependency 'hoe', '~> 3.12', :developer + self.dependency 'hoe-deveiate', '~> 0.6', :developer + self.dependency 'hoe-bundler', '~> 1.0', :developer + self.dependency 'rspec', '~> 3.0', :developer + + self.spec_extras[:licenses] = ['BSD', 'Ruby', 'GPL'] + self.spec_extras[:extensions] = [ 'ext/extconf.rb' ] + + self.require_ruby_version( '>= 1.9.3' ) + + self.hg_sign_tags = true if self.respond_to?( :hg_sign_tags= ) + self.check_history_on_release = true if self.respond_to?( :check_history_on_release= ) + + self.rdoc_locations << "deveiate:/usr/local/www/public/code/#{remote_rdoc_dir}" +end + +ENV['VERSION'] ||= $hoespec.spec.version.to_s + +# Tests should pass before checking in +task 'hg:precheckin' => [ :check_history, :check_manifest, :spec ] + +# Support for 'rvm specs' +task :specs => :spec + +# Compile before testing +task :spec => :compile + +# gem-testers support +task :test do + # rake-compiler always wants to copy the compiled extension into lib/, but + # we don't want testers to have to re-compile, especially since that + # often fails because they can't (and shouldn't have to) write to tmp/ in + # the installed gem dir. So we clear the task rake-compiler set up + # to break the dependency between :spec and :compile when running under + # rubygems-test, and then run :spec. + Rake::Task[ EXT.to_s ].clear + Rake::Task[ :spec ].execute +end + +desc "Turn on warnings and debugging in the build." +task :maint do + ENV['MAINTAINER_MODE'] = 'yes' +end + +ENV['RUBY_CC_VERSION'] ||= '1.8.7:1.9.2:2.0.0' + +# Rake-compiler task +Rake::ExtensionTask.new do |ext| + ext.name = 'pg_ext' + ext.gem_spec = $hoespec.spec + ext.ext_dir = 'ext' + ext.lib_dir = 'lib' + ext.source_pattern = "*.{c,h}" + ext.cross_compile = true + ext.cross_platform = CrossLibraries.map &:for_platform + + ext.cross_config_options += CrossLibraries.map do |lib| + { + lib.for_platform => [ + "--enable-windows-cross", + "--with-pg-include=#{lib.static_postgresql_incdir}", + "--with-pg-lib=#{lib.static_postgresql_libdir}", + # libpq-fe.h resides in src/interfaces/libpq/ before make install + "--with-opt-include=#{lib.static_postgresql_libdir}", + ] + } + end + + # Add libpq.dll to windows binary gemspec + ext.cross_compiling do |spec| + # mingw32-platform strings differ (RUBY_PLATFORM=i386-mingw32 vs. x86-mingw32 for rubygems) + spec.files << "lib/#{spec.platform.to_s.gsub(/^x86-/, "i386-")}/libpq.dll" + end +end + + +# Use the fivefish formatter for docs generated from development checkout +if File.directory?( '.hg' ) + require 'rdoc/task' + + Rake::Task[ 'docs' ].clear + RDoc::Task.new( 'docs' ) do |rdoc| + rdoc.main = "README.rdoc" + rdoc.rdoc_files.include( "*.rdoc", "ChangeLog", "lib/**/*.rb", 'ext/**/*.{c,h}' ) + rdoc.generator = :fivefish + rdoc.title = "PG: The Ruby PostgreSQL Driver" + rdoc.rdoc_dir = 'doc' + end +end + + +# Make the ChangeLog update if the repo has changed since it was last built +file '.hg/branch' do + warn "WARNING: You need the Mercurial repo to update the ChangeLog" +end +file 'ChangeLog' do |task| + if File.exist?('.hg/branch') + $stderr.puts "Updating the changelog..." + begin + include Hoe::MercurialHelpers + content = make_changelog() + rescue NameError + abort "Packaging tasks require the hoe-mercurial plugin (gem install hoe-mercurial)" + end + File.open( task.name, 'w', 0644 ) do |fh| + fh.print( content ) + end + else + touch 'ChangeLog' + end +end + +# Rebuild the ChangeLog immediately before release +task :prerelease => 'ChangeLog' + + +desc "Stop any Postmaster instances that remain after testing." +task :cleanup_testing_dbs do + require 'spec/lib/helpers' + PgTestingHelpers.stop_existing_postmasters() + Rake::Task[:clean].invoke +end + +desc "Update list of server error codes" +task :update_error_codes do + URL_ERRORCODES_TXT = "http://git.postgresql.org/gitweb/?p=postgresql.git;a=blob_plain;f=src/backend/utils/errcodes.txt;hb=HEAD" + + ERRORCODES_TXT = "ext/errorcodes.txt" + sh "wget #{URL_ERRORCODES_TXT.inspect} -O #{ERRORCODES_TXT.inspect} || curl #{URL_ERRORCODES_TXT.inspect} -o #{ERRORCODES_TXT.inspect}" +end + +file 'ext/errorcodes.def' => ['ext/errorcodes.rb', 'ext/errorcodes.txt'] do + ruby 'ext/errorcodes.rb', 'ext/errorcodes.txt', 'ext/errorcodes.def' +end + +file 'ext/pg_errors.c' => ['ext/errorcodes.def'] do + # trigger compilation of changed errorcodes.def + touch 'ext/pg_errors.c' +end + +task :gemspec => GEMSPEC +file GEMSPEC => __FILE__ +task GEMSPEC do |task| + spec = $hoespec.spec + spec.files.delete( '.gemtest' ) + spec.version = "#{spec.version}.pre#{Time.now.strftime("%Y%m%d%H%M%S")}" + File.open( task.name, 'w' ) do |fh| + fh.write( spec.to_ruby ) + end +end + +CLOBBER.include( GEMSPEC.to_s ) +task :default => :gemspec + diff --git a/dependency-check-core/src/test/resources/ruby/vulnerable/gems/rails-4.1.15/vendor/bundle/ruby/2.2.0/specifications/dalli-2.7.5.gemspec b/dependency-check-core/src/test/resources/ruby/vulnerable/gems/rails-4.1.15/vendor/bundle/ruby/2.2.0/specifications/dalli-2.7.5.gemspec new file mode 100644 index 000000000..8db8be505 --- /dev/null +++ b/dependency-check-core/src/test/resources/ruby/vulnerable/gems/rails-4.1.15/vendor/bundle/ruby/2.2.0/specifications/dalli-2.7.5.gemspec @@ -0,0 +1,54 @@ +# -*- encoding: utf-8 -*- +# stub: dalli 2.7.5 ruby lib + +Gem::Specification.new do |s| + s.name = "dalli" + s.version = "2.7.5" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.require_paths = ["lib"] + s.authors = ["Peter M. Goldstein", "Mike Perham"] + s.date = "2015-12-16" + s.description = "High performance memcached client for Ruby" + s.email = ["peter.m.goldstein@gmail.com", "mperham@gmail.com"] + s.homepage = "https://github.com/petergoldstein/dalli" + s.licenses = ["MIT"] + s.rdoc_options = ["--charset=UTF-8"] + s.rubygems_version = "2.5.0" + s.summary = "High performance memcached client for Ruby" + + s.installed_by_version = "2.5.0" if s.respond_to? :installed_by_version + + if s.respond_to? :specification_version then + s.specification_version = 4 + + if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then + s.add_development_dependency(%q, [">= 4.2.0"]) + s.add_development_dependency(%q, [">= 0"]) + s.add_development_dependency(%q, ["~> 4"]) + s.add_development_dependency(%q, [">= 0"]) + s.add_development_dependency(%q, [">= 0"]) + s.add_development_dependency(%q, [">= 0"]) + s.add_development_dependency(%q, [">= 0"]) + s.add_development_dependency(%q, [">= 0"]) + else + s.add_dependency(%q, [">= 4.2.0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, ["~> 4"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + end + else + s.add_dependency(%q, [">= 4.2.0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, ["~> 4"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + end +end From d5e8f54214b8c850434c216a5196dbd453afb6b2 Mon Sep 17 00:00:00 2001 From: bjiang Date: Fri, 6 May 2016 17:55:21 -0400 Subject: [PATCH 8/8] fix RubyBundlerAnalyzer.accept --- .../analyzer/RubyBundlerAnalyzer.java | 12 +++++++++++- .../analyzer/RubyBundlerAnalyzerTest.java | 3 ++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.java index 6d17f7aa1..7bfda9cf0 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.java @@ -55,6 +55,16 @@ public class RubyBundlerAnalyzer extends RubyGemspecAnalyzer { //Folder name that contains the gems by "bundle install" private static final String GEMS = "gems"; + /** + * Returns the name of the analyzer. + * + * @return the name of the analyzer. + */ + @Override + public String getName() { + return ANALYZER_NAME; + } + /** * Only accept *.gemspec files generated by "bundle install --deployment" under "specifications" folder. */ @@ -64,7 +74,7 @@ public class RubyBundlerAnalyzer extends RubyGemspecAnalyzer { boolean accepted = super.accept(pathname); if(accepted == true) { File parentDir = pathname.getParentFile(); - accepted = parentDir != null && parentDir.exists() && parentDir.getName().equals(SPECIFICATIONS); + accepted = parentDir != null && parentDir.getName().equals(SPECIFICATIONS); } return accepted; diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzerTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzerTest.java index bff57eeff..d304a4200 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzerTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzerTest.java @@ -78,7 +78,8 @@ public class RubyBundlerAnalyzerTest extends BaseTest { */ @Test public void testSupportsFiles() { - assertThat(analyzer.accept(new File("test.gemspec")), is(true)); + assertThat(analyzer.accept(new File("test.gemspec")), is(false)); + assertThat(analyzer.accept(new File("specifications" + File.separator + "test.gemspec")), is(true)); } /**